@flopay/react 1.3.4 → 1.4.1
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 +25 -0
- package/dist/index.cjs +1508 -788
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -10
- package/dist/index.d.ts +7 -10
- package/dist/index.mjs +1349 -630
- package/dist/index.mjs.map +1 -1
- package/dist/payment-logos/alipay.svg +1 -0
- package/dist/payment-logos/bancontact.svg +1 -0
- package/dist/payment-logos/blik.svg +1 -0
- package/dist/payment-logos/eps.svg +1 -0
- package/dist/payment-logos/giropay.svg +1 -0
- package/dist/payment-logos/ideal.svg +1 -0
- package/dist/payment-logos/klarna.svg +1 -0
- package/dist/payment-logos/p24.svg +1 -0
- package/dist/payment-logos/sepa_debit.svg +1 -0
- package/dist/payment-logos/wechat_pay.svg +1 -0
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -69,6 +69,59 @@ var CheckoutContext = (0, import_react.createContext)({
|
|
|
69
69
|
error: null
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
+
// src/telemetry-bridge.ts
|
|
73
|
+
var FLOPAY_TELEMETRY_BRIDGE = /* @__PURE__ */ Symbol.for("@flopay/js.telemetry.bridge.v1");
|
|
74
|
+
var TELEMETRY_REPORTER_FACTORY = /* @__PURE__ */ Symbol.for("@flopay/js.telemetry.reporter-factory.v1");
|
|
75
|
+
function noopTelemetryBridge() {
|
|
76
|
+
return {
|
|
77
|
+
error: () => {
|
|
78
|
+
},
|
|
79
|
+
log: () => {
|
|
80
|
+
},
|
|
81
|
+
performance: () => {
|
|
82
|
+
},
|
|
83
|
+
terminal: () => {
|
|
84
|
+
},
|
|
85
|
+
now: () => globalThis.performance?.now() ?? 0,
|
|
86
|
+
elapsed: (startedAt) => Math.max(0, (globalThis.performance?.now() ?? startedAt) - startedAt),
|
|
87
|
+
setCheckoutContext: () => {
|
|
88
|
+
},
|
|
89
|
+
beginCheckout: () => globalThis.performance?.now() ?? 0,
|
|
90
|
+
disable: () => {
|
|
91
|
+
},
|
|
92
|
+
flush: async () => {
|
|
93
|
+
},
|
|
94
|
+
destroy: () => {
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function normalizeTelemetryBridge(source) {
|
|
99
|
+
const fallback = noopTelemetryBridge();
|
|
100
|
+
const bind = (candidate, defaultValue) => candidate ? candidate.bind(source) : defaultValue;
|
|
101
|
+
const now = bind(source.now, fallback.now);
|
|
102
|
+
return {
|
|
103
|
+
error: bind(source.error, fallback.error),
|
|
104
|
+
log: bind(source.log, fallback.log),
|
|
105
|
+
performance: bind(source.performance, fallback.performance),
|
|
106
|
+
terminal: bind(source.terminal, fallback.terminal),
|
|
107
|
+
now,
|
|
108
|
+
elapsed: source.elapsed ? source.elapsed.bind(source) : (startedAt) => Math.max(0, now() - startedAt),
|
|
109
|
+
setCheckoutContext: bind(source.setCheckoutContext, fallback.setCheckoutContext),
|
|
110
|
+
beginCheckout: bind(source.beginCheckout, fallback.beginCheckout),
|
|
111
|
+
disable: bind(source.disable, fallback.disable),
|
|
112
|
+
flush: bind(source.flush, fallback.flush),
|
|
113
|
+
destroy: bind(source.destroy, fallback.destroy)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function createTelemetryBridge(options) {
|
|
117
|
+
const factory = globalThis[TELEMETRY_REPORTER_FACTORY];
|
|
118
|
+
return normalizeTelemetryBridge(factory?.(options) ?? {});
|
|
119
|
+
}
|
|
120
|
+
function getFloPayTelemetryBridge(floPay) {
|
|
121
|
+
if (!floPay) return void 0;
|
|
122
|
+
return floPay[FLOPAY_TELEMETRY_BRIDGE];
|
|
123
|
+
}
|
|
124
|
+
|
|
72
125
|
// src/provider.tsx
|
|
73
126
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
74
127
|
function FloPayProvider({
|
|
@@ -84,6 +137,18 @@ function FloPayProvider({
|
|
|
84
137
|
paypalFloPayProp instanceof Promise || !paypalFloPayProp ? null : paypalFloPayProp
|
|
85
138
|
);
|
|
86
139
|
const [elements, setElements] = (0, import_react2.useState)(null);
|
|
140
|
+
const mountedAt = (0, import_react2.useRef)(null);
|
|
141
|
+
const renderedElements = (0, import_react2.useRef)(null);
|
|
142
|
+
const interactiveElements = (0, import_react2.useRef)(null);
|
|
143
|
+
(0, import_react2.useEffect)(() => {
|
|
144
|
+
if (!flopay) return;
|
|
145
|
+
const telemetry = getFloPayTelemetryBridge(flopay);
|
|
146
|
+
mountedAt.current = telemetry?.beginCheckout() ?? telemetry?.now() ?? 0;
|
|
147
|
+
telemetry?.log({ name: "checkout.mount", stage: "checkout_mount" });
|
|
148
|
+
return () => {
|
|
149
|
+
telemetry?.log({ name: "checkout.unmount", stage: "unmount" });
|
|
150
|
+
};
|
|
151
|
+
}, [flopay]);
|
|
87
152
|
(0, import_react2.useEffect)(() => {
|
|
88
153
|
let cancelled = false;
|
|
89
154
|
if (floPayProp instanceof Promise) {
|
|
@@ -144,16 +209,44 @@ function FloPayProvider({
|
|
|
144
209
|
options?.paymentMethodCreation,
|
|
145
210
|
options?.setupFutureUsage
|
|
146
211
|
]);
|
|
212
|
+
(0, import_react2.useEffect)(() => {
|
|
213
|
+
if (!flopay || !elements || renderedElements.current === elements) return;
|
|
214
|
+
renderedElements.current = elements;
|
|
215
|
+
const telemetry = getFloPayTelemetryBridge(flopay);
|
|
216
|
+
telemetry?.log({ name: "checkout.rendered", stage: "checkout_render" });
|
|
217
|
+
telemetry?.performance({
|
|
218
|
+
stage: "checkout_render",
|
|
219
|
+
durationMs: telemetry.elapsed(mountedAt.current ?? 0),
|
|
220
|
+
durationMode: "machine"
|
|
221
|
+
});
|
|
222
|
+
}, [elements, flopay]);
|
|
223
|
+
const reportInteractive = (0, import_react2.useCallback)(() => {
|
|
224
|
+
if (!flopay || !elements || interactiveElements.current === elements) return;
|
|
225
|
+
interactiveElements.current = elements;
|
|
226
|
+
const telemetry = getFloPayTelemetryBridge(flopay);
|
|
227
|
+
telemetry?.log({ name: "checkout.interactive", stage: "checkout_interactive" });
|
|
228
|
+
telemetry?.performance({
|
|
229
|
+
stage: "checkout_interactive",
|
|
230
|
+
durationMs: telemetry.elapsed(mountedAt.current ?? 0),
|
|
231
|
+
durationMode: "machine"
|
|
232
|
+
});
|
|
233
|
+
}, [elements, flopay]);
|
|
147
234
|
const resolvedBillingApiUrl = (0, import_shared.resolveBillingApiUrl)(options?.billingApiUrl);
|
|
148
235
|
const value = (0, import_react2.useMemo)(
|
|
149
|
-
() => ({
|
|
150
|
-
|
|
236
|
+
() => ({
|
|
237
|
+
flopay,
|
|
238
|
+
paypalFlopay,
|
|
239
|
+
elements,
|
|
240
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
241
|
+
reportInteractive
|
|
242
|
+
}),
|
|
243
|
+
[flopay, paypalFlopay, elements, resolvedBillingApiUrl, reportInteractive]
|
|
151
244
|
);
|
|
152
245
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FloPayContext.Provider, { value, children });
|
|
153
246
|
}
|
|
154
247
|
|
|
155
248
|
// src/flopay-checkout.tsx
|
|
156
|
-
var
|
|
249
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
157
250
|
var import_js4 = require("@flopay/js");
|
|
158
251
|
var import_shared8 = require("@flopay/shared");
|
|
159
252
|
|
|
@@ -241,7 +334,7 @@ function createElementComponent(elementType, displayName) {
|
|
|
241
334
|
}) {
|
|
242
335
|
const containerRef = (0, import_react4.useRef)(null);
|
|
243
336
|
const elementRef = (0, import_react4.useRef)(null);
|
|
244
|
-
const { elements } = (0, import_react4.useContext)(FloPayContext);
|
|
337
|
+
const { elements, reportInteractive } = (0, import_react4.useContext)(FloPayContext);
|
|
245
338
|
(0, import_react4.useEffect)(() => {
|
|
246
339
|
if (!elements || !containerRef.current) return;
|
|
247
340
|
let mounted = true;
|
|
@@ -256,7 +349,10 @@ function createElementComponent(elementType, displayName) {
|
|
|
256
349
|
element.mount(containerRef.current);
|
|
257
350
|
elementRef.current = element;
|
|
258
351
|
if (onChange) element.on("change", onChange);
|
|
259
|
-
|
|
352
|
+
element.on("ready", () => {
|
|
353
|
+
reportInteractive?.();
|
|
354
|
+
onReady?.();
|
|
355
|
+
});
|
|
260
356
|
if (onFocus) element.on("focus", onFocus);
|
|
261
357
|
if (onBlur) element.on("blur", onBlur);
|
|
262
358
|
if (onEscape) element.on("escape", onEscape);
|
|
@@ -271,7 +367,7 @@ function createElementComponent(elementType, displayName) {
|
|
|
271
367
|
elementRef.current = null;
|
|
272
368
|
}
|
|
273
369
|
};
|
|
274
|
-
}, [elements]);
|
|
370
|
+
}, [elements, reportInteractive]);
|
|
275
371
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: containerRef, className, id, style });
|
|
276
372
|
}
|
|
277
373
|
ElementComponent.displayName = displayName;
|
|
@@ -360,42 +456,100 @@ function VaultCardFields({
|
|
|
360
456
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: containerRef, "data-testid": "flopay-vault-card-fields", style: containerStyle });
|
|
361
457
|
}
|
|
362
458
|
|
|
459
|
+
// src/error-banner.tsx
|
|
460
|
+
var import_react6 = require("react");
|
|
461
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
462
|
+
function ErrorBanner({
|
|
463
|
+
children,
|
|
464
|
+
margin,
|
|
465
|
+
icon = true,
|
|
466
|
+
styleOverride
|
|
467
|
+
}) {
|
|
468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
469
|
+
"div",
|
|
470
|
+
{
|
|
471
|
+
role: "alert",
|
|
472
|
+
"data-testid": "flopay-error",
|
|
473
|
+
style: {
|
|
474
|
+
margin,
|
|
475
|
+
padding: "0.625rem 0.875rem",
|
|
476
|
+
background: "#FEF2F2",
|
|
477
|
+
border: "1px solid #FECACA",
|
|
478
|
+
borderRadius: "8px",
|
|
479
|
+
color: "#991B1B",
|
|
480
|
+
fontSize: "0.85rem",
|
|
481
|
+
fontWeight: 600,
|
|
482
|
+
...icon ? { display: "flex", alignItems: "center", gap: "0.5rem" } : {},
|
|
483
|
+
...styleOverride ?? {}
|
|
484
|
+
},
|
|
485
|
+
children: [
|
|
486
|
+
icon && /* @__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)(
|
|
487
|
+
"path",
|
|
488
|
+
{
|
|
489
|
+
d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z",
|
|
490
|
+
stroke: "#DC2626",
|
|
491
|
+
strokeWidth: "2",
|
|
492
|
+
strokeLinecap: "round",
|
|
493
|
+
strokeLinejoin: "round"
|
|
494
|
+
}
|
|
495
|
+
) }),
|
|
496
|
+
children
|
|
497
|
+
]
|
|
498
|
+
}
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// src/payment-logos.generated.ts
|
|
503
|
+
var import_meta = {};
|
|
504
|
+
var PAYMENT_METHOD_LOGO_URLS = {
|
|
505
|
+
"alipay": new URL("./payment-logos/alipay.svg", import_meta.url).href,
|
|
506
|
+
"bancontact": new URL("./payment-logos/bancontact.svg", import_meta.url).href,
|
|
507
|
+
"blik": new URL("./payment-logos/blik.svg", import_meta.url).href,
|
|
508
|
+
"eps": new URL("./payment-logos/eps.svg", import_meta.url).href,
|
|
509
|
+
"giropay": new URL("./payment-logos/giropay.svg", import_meta.url).href,
|
|
510
|
+
"ideal": new URL("./payment-logos/ideal.svg", import_meta.url).href,
|
|
511
|
+
"klarna": new URL("./payment-logos/klarna.svg", import_meta.url).href,
|
|
512
|
+
"p24": new URL("./payment-logos/p24.svg", import_meta.url).href,
|
|
513
|
+
"sepa_debit": new URL("./payment-logos/sepa_debit.svg", import_meta.url).href,
|
|
514
|
+
"wechat_pay": new URL("./payment-logos/wechat_pay.svg", import_meta.url).href
|
|
515
|
+
};
|
|
516
|
+
|
|
363
517
|
// src/split-card-form.tsx
|
|
364
|
-
var
|
|
518
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
365
519
|
|
|
366
520
|
// src/hooks.ts
|
|
367
|
-
var
|
|
521
|
+
var import_react7 = require("react");
|
|
368
522
|
var import_shared2 = require("@flopay/shared");
|
|
369
523
|
function useFloPay() {
|
|
370
|
-
const ctx = (0,
|
|
524
|
+
const ctx = (0, import_react7.useContext)(FloPayContext);
|
|
371
525
|
return ctx.flopay;
|
|
372
526
|
}
|
|
373
527
|
function usePayPalFloPay() {
|
|
374
|
-
const ctx = (0,
|
|
528
|
+
const ctx = (0, import_react7.useContext)(FloPayContext);
|
|
375
529
|
return ctx.paypalFlopay ?? null;
|
|
376
530
|
}
|
|
377
531
|
function useElements() {
|
|
378
|
-
const ctx = (0,
|
|
532
|
+
const ctx = (0, import_react7.useContext)(FloPayContext);
|
|
379
533
|
return ctx.elements;
|
|
380
534
|
}
|
|
381
535
|
function useCheckout() {
|
|
382
|
-
return (0,
|
|
536
|
+
return (0, import_react7.useContext)(CheckoutContext);
|
|
383
537
|
}
|
|
384
538
|
function useBillingApiUrl() {
|
|
385
|
-
const ctx = (0,
|
|
539
|
+
const ctx = (0, import_react7.useContext)(FloPayContext);
|
|
386
540
|
return ctx.billingApiUrl || (0, import_shared2.resolveBillingApiUrl)();
|
|
387
541
|
}
|
|
388
542
|
|
|
389
543
|
// src/processing-overlay.tsx
|
|
390
|
-
var
|
|
391
|
-
var
|
|
544
|
+
var import_react8 = require("react");
|
|
545
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
392
546
|
var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
|
|
393
547
|
var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
|
|
394
548
|
function ProcessingOverlay({
|
|
395
549
|
status,
|
|
396
550
|
errorMessage
|
|
397
551
|
}) {
|
|
398
|
-
return /* @__PURE__ */ (0,
|
|
552
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
399
553
|
"div",
|
|
400
554
|
{
|
|
401
555
|
"data-testid": "flopay-processing-overlay",
|
|
@@ -412,7 +566,7 @@ function ProcessingOverlay({
|
|
|
412
566
|
zIndex: 1e3,
|
|
413
567
|
backdropFilter: "blur(2px)"
|
|
414
568
|
},
|
|
415
|
-
children: /* @__PURE__ */ (0,
|
|
569
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
416
570
|
"div",
|
|
417
571
|
{
|
|
418
572
|
style: {
|
|
@@ -428,8 +582,8 @@ function ProcessingOverlay({
|
|
|
428
582
|
gap: 16
|
|
429
583
|
},
|
|
430
584
|
children: [
|
|
431
|
-
/* @__PURE__ */ (0,
|
|
432
|
-
status === "processing" && /* @__PURE__ */ (0,
|
|
585
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { width: 48, height: 48, position: "relative" }, children: [
|
|
586
|
+
status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
433
587
|
"svg",
|
|
434
588
|
{
|
|
435
589
|
width: "48",
|
|
@@ -439,14 +593,14 @@ function ProcessingOverlay({
|
|
|
439
593
|
xmlns: "http://www.w3.org/2000/svg",
|
|
440
594
|
style: { animation: "flopay-spin 0.8s linear infinite" },
|
|
441
595
|
children: [
|
|
442
|
-
/* @__PURE__ */ (0,
|
|
443
|
-
/* @__PURE__ */ (0,
|
|
596
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
|
|
444
598
|
]
|
|
445
599
|
}
|
|
446
600
|
),
|
|
447
|
-
status === "success" && /* @__PURE__ */ (0,
|
|
448
|
-
/* @__PURE__ */ (0,
|
|
449
|
-
/* @__PURE__ */ (0,
|
|
601
|
+
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
602
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
|
|
603
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
450
604
|
"path",
|
|
451
605
|
{
|
|
452
606
|
d: "M7 12.5l3 3 7-7",
|
|
@@ -462,9 +616,9 @@ function ProcessingOverlay({
|
|
|
462
616
|
}
|
|
463
617
|
)
|
|
464
618
|
] }) }),
|
|
465
|
-
status === "error" && /* @__PURE__ */ (0,
|
|
466
|
-
/* @__PURE__ */ (0,
|
|
467
|
-
/* @__PURE__ */ (0,
|
|
619
|
+
status === "error" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
620
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
|
|
621
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
468
622
|
"path",
|
|
469
623
|
{
|
|
470
624
|
d: "M8 8l8 8M16 8l-8 8",
|
|
@@ -480,7 +634,7 @@ function ProcessingOverlay({
|
|
|
480
634
|
)
|
|
481
635
|
] }) })
|
|
482
636
|
] }),
|
|
483
|
-
/* @__PURE__ */ (0,
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
484
638
|
"span",
|
|
485
639
|
{
|
|
486
640
|
style: {
|
|
@@ -496,7 +650,7 @@ function ProcessingOverlay({
|
|
|
496
650
|
]
|
|
497
651
|
}
|
|
498
652
|
),
|
|
499
|
-
status === "success" && /* @__PURE__ */ (0,
|
|
653
|
+
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
500
654
|
"p",
|
|
501
655
|
{
|
|
502
656
|
style: {
|
|
@@ -510,7 +664,7 @@ function ProcessingOverlay({
|
|
|
510
664
|
children: "You will be automatically redirected, do not close or navigate away from this window."
|
|
511
665
|
}
|
|
512
666
|
),
|
|
513
|
-
status === "error" && errorMessage && /* @__PURE__ */ (0,
|
|
667
|
+
status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
514
668
|
"p",
|
|
515
669
|
{
|
|
516
670
|
style: {
|
|
@@ -524,7 +678,7 @@ function ProcessingOverlay({
|
|
|
524
678
|
children: errorMessage
|
|
525
679
|
}
|
|
526
680
|
),
|
|
527
|
-
/* @__PURE__ */ (0,
|
|
681
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
|
|
528
682
|
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
529
683
|
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
530
684
|
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
@@ -686,6 +840,14 @@ async function buildFloPayApiErrorFromResponse(response, fallbackMessage) {
|
|
|
686
840
|
const payload = await response.json().catch(() => null);
|
|
687
841
|
return buildFloPayApiError(payload, fallbackMessage);
|
|
688
842
|
}
|
|
843
|
+
function intentRequestHeaders(nonce) {
|
|
844
|
+
const headers = { "Content-Type": "application/json" };
|
|
845
|
+
if (nonce) headers["x-checkout-session-token"] = nonce;
|
|
846
|
+
return headers;
|
|
847
|
+
}
|
|
848
|
+
function isSuccessfulPaymentIntentStatus(status) {
|
|
849
|
+
return status === "succeeded" || status === "requires_capture" || status === "processing";
|
|
850
|
+
}
|
|
689
851
|
function mapPayPalIntentStatusToPaymentResult(status) {
|
|
690
852
|
if (status === "succeeded") {
|
|
691
853
|
return "succeeded";
|
|
@@ -798,11 +960,24 @@ function isInAppBrowser(userAgent) {
|
|
|
798
960
|
}
|
|
799
961
|
|
|
800
962
|
// src/direct-paypal-button.tsx
|
|
801
|
-
var
|
|
963
|
+
var import_react9 = require("react");
|
|
802
964
|
var import_paypal_js = require("@paypal/paypal-js");
|
|
803
965
|
var import_js = require("@flopay/js");
|
|
804
966
|
var import_shared4 = require("@flopay/shared");
|
|
805
967
|
|
|
968
|
+
// src/merchant-callback.ts
|
|
969
|
+
function invokeMerchantCallback(callback) {
|
|
970
|
+
if (!callback) return;
|
|
971
|
+
const reportFailure = (error) => {
|
|
972
|
+
console.error("[FloPay] Merchant callback failed; checkout continued.", error);
|
|
973
|
+
};
|
|
974
|
+
try {
|
|
975
|
+
void Promise.resolve(callback()).catch(reportFailure);
|
|
976
|
+
} catch (error) {
|
|
977
|
+
reportFailure(error);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
806
981
|
// src/external-method-recovery.ts
|
|
807
982
|
var EXTERNAL_METHOD_CALLBACK_GRACE_MS = 600;
|
|
808
983
|
function getProviderErrorMessage(err) {
|
|
@@ -840,7 +1015,7 @@ function isPopupBlockedError(err) {
|
|
|
840
1015
|
}
|
|
841
1016
|
|
|
842
1017
|
// src/direct-paypal-button.tsx
|
|
843
|
-
var
|
|
1018
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
844
1019
|
var DEFAULT_BUTTON_HEIGHT = 45;
|
|
845
1020
|
var DIRECT_PAYPAL_RECOVERY_MESSAGE = "We couldn't open PayPal. Try again or choose another payment method.";
|
|
846
1021
|
var DIRECT_PAYPAL_RECOVERY_ACTION_STYLE = {
|
|
@@ -859,7 +1034,7 @@ var DIRECT_PAYPAL_RECOVERY_ACTION_STYLE = {
|
|
|
859
1034
|
function buildDirectPayPalRecoveryMessage(popupBlocked) {
|
|
860
1035
|
return popupBlocked ? `${DIRECT_PAYPAL_RECOVERY_MESSAGE} Allow pop-ups for this site, then try again.` : DIRECT_PAYPAL_RECOVERY_MESSAGE;
|
|
861
1036
|
}
|
|
862
|
-
function
|
|
1037
|
+
function DirectPayPalButtonImplementation({
|
|
863
1038
|
sessionId,
|
|
864
1039
|
nonce,
|
|
865
1040
|
billingApiUrl,
|
|
@@ -879,101 +1054,149 @@ function DirectPayPalButton({
|
|
|
879
1054
|
runBeforeButtonClick,
|
|
880
1055
|
session,
|
|
881
1056
|
existingOrderId,
|
|
1057
|
+
telemetry,
|
|
1058
|
+
telemetryContext,
|
|
882
1059
|
debug = false
|
|
883
1060
|
}) {
|
|
884
|
-
const
|
|
885
|
-
const
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1061
|
+
const flopay = useFloPay();
|
|
1062
|
+
const standaloneTelemetry = (0, import_react9.useMemo)(() => {
|
|
1063
|
+
if (flopay) return null;
|
|
1064
|
+
const reporter = createTelemetryBridge({
|
|
1065
|
+
billingApiUrl,
|
|
1066
|
+
sdkPackage: "@flopay/react",
|
|
1067
|
+
sdkVersion: import_shared4.SDK_VERSION,
|
|
1068
|
+
enabled: telemetry !== false
|
|
1069
|
+
});
|
|
1070
|
+
reporter.setCheckoutContext(telemetryContext ?? {});
|
|
1071
|
+
reporter.beginCheckout(telemetryContext ?? {});
|
|
1072
|
+
return reporter;
|
|
1073
|
+
}, [
|
|
1074
|
+
billingApiUrl,
|
|
1075
|
+
flopay,
|
|
1076
|
+
telemetry,
|
|
1077
|
+
telemetryContext?.checkoutMode,
|
|
1078
|
+
telemetryContext?.layout
|
|
1079
|
+
]);
|
|
1080
|
+
const floPayTelemetry = (0, import_react9.useMemo)(() => getFloPayTelemetryBridge(flopay), [flopay]);
|
|
1081
|
+
(0, import_react9.useEffect)(() => () => {
|
|
1082
|
+
if (!standaloneTelemetry) return;
|
|
1083
|
+
void standaloneTelemetry.flush().catch(() => {
|
|
1084
|
+
}).finally(() => standaloneTelemetry.destroy());
|
|
1085
|
+
}, [standaloneTelemetry]);
|
|
1086
|
+
const telemetrySource = (0, import_react9.useMemo)(() => ({
|
|
1087
|
+
error: (input) => {
|
|
1088
|
+
if (floPayTelemetry) floPayTelemetry.error(input);
|
|
1089
|
+
else standaloneTelemetry?.error(input);
|
|
1090
|
+
},
|
|
1091
|
+
log: (input) => {
|
|
1092
|
+
if (floPayTelemetry) floPayTelemetry.log(input);
|
|
1093
|
+
else standaloneTelemetry?.log(input);
|
|
1094
|
+
},
|
|
1095
|
+
performance: (input) => {
|
|
1096
|
+
if (floPayTelemetry) floPayTelemetry.performance(input);
|
|
1097
|
+
else standaloneTelemetry?.performance(input);
|
|
1098
|
+
},
|
|
1099
|
+
terminal: (input) => {
|
|
1100
|
+
if (floPayTelemetry) floPayTelemetry.terminal(input);
|
|
1101
|
+
else standaloneTelemetry?.terminal(input);
|
|
1102
|
+
},
|
|
1103
|
+
startTiming: () => floPayTelemetry?.now() ?? standaloneTelemetry?.now() ?? 0,
|
|
1104
|
+
elapsed: (startedAt) => floPayTelemetry?.elapsed(startedAt) ?? Math.max(0, (standaloneTelemetry?.now() ?? startedAt) - startedAt)
|
|
1105
|
+
}), [floPayTelemetry, standaloneTelemetry]);
|
|
1106
|
+
const containerRef = (0, import_react9.useRef)(null);
|
|
1107
|
+
const providerStartedAt = (0, import_react9.useRef)(0);
|
|
1108
|
+
const focusTargetRef = (0, import_react9.useRef)(null);
|
|
1109
|
+
const pendingProviderFocusRef = (0, import_react9.useRef)(false);
|
|
1110
|
+
const [ready, setReady] = (0, import_react9.useState)(false);
|
|
1111
|
+
const [renderGeneration, setRenderGeneration] = (0, import_react9.useState)(0);
|
|
1112
|
+
const activeRenderGenerationRef = (0, import_react9.useRef)(0);
|
|
1113
|
+
const [showRetryFocusTarget, setShowRetryFocusTarget] = (0, import_react9.useState)(false);
|
|
1114
|
+
const [failed, setFailed] = (0, import_react9.useState)(false);
|
|
1115
|
+
const [submitting, setSubmitting] = (0, import_react9.useState)(false);
|
|
1116
|
+
const baseUrl = (0, import_react9.useMemo)(() => billingApiUrl.replace(/\/+$/, ""), [billingApiUrl]);
|
|
1117
|
+
const [debugLines, setDebugLines] = (0, import_react9.useState)([]);
|
|
895
1118
|
const appendDebug = (line) => {
|
|
896
1119
|
if (!debug) return;
|
|
897
1120
|
setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
|
|
898
1121
|
};
|
|
899
|
-
const onTokenizedBodyRef = (0,
|
|
900
|
-
const onCompleteRef = (0,
|
|
901
|
-
const onErrorChangeRef = (0,
|
|
902
|
-
const onDeclineRef = (0,
|
|
903
|
-
const onTechnicalFailureRef = (0,
|
|
904
|
-
const onButtonClickRef = (0,
|
|
905
|
-
const onLoadStateChangeRef = (0,
|
|
906
|
-
const runBeforeButtonClickRef = (0,
|
|
907
|
-
const sessionRef = (0,
|
|
908
|
-
const emailRef = (0,
|
|
909
|
-
const nonceRef = (0,
|
|
910
|
-
const beforeClickRef = (0,
|
|
911
|
-
const attemptGenerationRef = (0,
|
|
912
|
-
const attemptRef = (0,
|
|
913
|
-
const invalidatedAttemptGenerationRef = (0,
|
|
914
|
-
const attemptContextBySurfaceRef = (0,
|
|
915
|
-
const approvalContextByTokenRef = (0,
|
|
916
|
-
(0,
|
|
1122
|
+
const onTokenizedBodyRef = (0, import_react9.useRef)(onTokenizedBody);
|
|
1123
|
+
const onCompleteRef = (0, import_react9.useRef)(onComplete);
|
|
1124
|
+
const onErrorChangeRef = (0, import_react9.useRef)(onErrorChange);
|
|
1125
|
+
const onDeclineRef = (0, import_react9.useRef)(onDecline);
|
|
1126
|
+
const onTechnicalFailureRef = (0, import_react9.useRef)(onTechnicalFailure);
|
|
1127
|
+
const onButtonClickRef = (0, import_react9.useRef)(onButtonClick);
|
|
1128
|
+
const onLoadStateChangeRef = (0, import_react9.useRef)(onLoadStateChange);
|
|
1129
|
+
const runBeforeButtonClickRef = (0, import_react9.useRef)(runBeforeButtonClick);
|
|
1130
|
+
const sessionRef = (0, import_react9.useRef)(session);
|
|
1131
|
+
const emailRef = (0, import_react9.useRef)(email);
|
|
1132
|
+
const nonceRef = (0, import_react9.useRef)(nonce);
|
|
1133
|
+
const beforeClickRef = (0, import_react9.useRef)(null);
|
|
1134
|
+
const attemptGenerationRef = (0, import_react9.useRef)(0);
|
|
1135
|
+
const attemptRef = (0, import_react9.useRef)(null);
|
|
1136
|
+
const invalidatedAttemptGenerationRef = (0, import_react9.useRef)(null);
|
|
1137
|
+
const attemptContextBySurfaceRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
1138
|
+
const approvalContextByTokenRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
1139
|
+
(0, import_react9.useEffect)(() => {
|
|
917
1140
|
onTokenizedBodyRef.current = onTokenizedBody;
|
|
918
1141
|
}, [onTokenizedBody]);
|
|
919
|
-
(0,
|
|
1142
|
+
(0, import_react9.useEffect)(() => {
|
|
920
1143
|
onCompleteRef.current = onComplete;
|
|
921
1144
|
}, [onComplete]);
|
|
922
|
-
(0,
|
|
1145
|
+
(0, import_react9.useEffect)(() => {
|
|
923
1146
|
onErrorChangeRef.current = onErrorChange;
|
|
924
1147
|
}, [onErrorChange]);
|
|
925
|
-
(0,
|
|
1148
|
+
(0, import_react9.useEffect)(() => {
|
|
926
1149
|
onDeclineRef.current = onDecline;
|
|
927
1150
|
}, [onDecline]);
|
|
928
|
-
(0,
|
|
1151
|
+
(0, import_react9.useEffect)(() => {
|
|
929
1152
|
onTechnicalFailureRef.current = onTechnicalFailure;
|
|
930
1153
|
}, [onTechnicalFailure]);
|
|
931
|
-
(0,
|
|
1154
|
+
(0, import_react9.useEffect)(() => {
|
|
932
1155
|
onButtonClickRef.current = onButtonClick;
|
|
933
1156
|
}, [onButtonClick]);
|
|
934
|
-
(0,
|
|
1157
|
+
(0, import_react9.useEffect)(() => {
|
|
935
1158
|
onLoadStateChangeRef.current = onLoadStateChange;
|
|
936
1159
|
}, [onLoadStateChange]);
|
|
937
|
-
(0,
|
|
1160
|
+
(0, import_react9.useEffect)(() => {
|
|
938
1161
|
runBeforeButtonClickRef.current = runBeforeButtonClick;
|
|
939
1162
|
}, [runBeforeButtonClick]);
|
|
940
|
-
(0,
|
|
1163
|
+
(0, import_react9.useEffect)(() => {
|
|
941
1164
|
sessionRef.current = session;
|
|
942
1165
|
}, [session]);
|
|
943
|
-
(0,
|
|
1166
|
+
(0, import_react9.useEffect)(() => {
|
|
944
1167
|
emailRef.current = email;
|
|
945
1168
|
}, [email]);
|
|
946
|
-
(0,
|
|
1169
|
+
(0, import_react9.useEffect)(() => {
|
|
947
1170
|
nonceRef.current = nonce;
|
|
948
1171
|
}, [nonce]);
|
|
949
|
-
(0,
|
|
1172
|
+
(0, import_react9.useEffect)(() => {
|
|
950
1173
|
activeRenderGenerationRef.current = renderGeneration;
|
|
951
1174
|
}, [renderGeneration]);
|
|
952
|
-
(0,
|
|
1175
|
+
(0, import_react9.useEffect)(() => {
|
|
953
1176
|
if (showRetryFocusTarget) focusTargetRef.current?.focus();
|
|
954
1177
|
}, [showRetryFocusTarget, renderGeneration]);
|
|
955
|
-
const focusRetryTarget = (0,
|
|
1178
|
+
const focusRetryTarget = (0, import_react9.useCallback)(() => {
|
|
956
1179
|
window.setTimeout(() => {
|
|
957
1180
|
focusTargetRef.current?.focus();
|
|
958
1181
|
}, 0);
|
|
959
1182
|
}, []);
|
|
960
|
-
const remountPayPalButtons = (0,
|
|
1183
|
+
const remountPayPalButtons = (0, import_react9.useCallback)(() => {
|
|
961
1184
|
setReady(false);
|
|
962
1185
|
setRenderGeneration((current) => current + 1);
|
|
963
1186
|
}, []);
|
|
964
|
-
const focusPayPalSurface = (0,
|
|
1187
|
+
const focusPayPalSurface = (0, import_react9.useCallback)(() => {
|
|
965
1188
|
setShowRetryFocusTarget(false);
|
|
966
1189
|
const target = containerRef.current?.querySelector(
|
|
967
1190
|
'iframe, button, [tabindex]:not([tabindex="-1"])'
|
|
968
1191
|
);
|
|
969
1192
|
(target ?? containerRef.current)?.focus?.();
|
|
970
1193
|
}, []);
|
|
971
|
-
(0,
|
|
1194
|
+
(0, import_react9.useEffect)(() => {
|
|
972
1195
|
if (!ready || !pendingProviderFocusRef.current) return;
|
|
973
1196
|
pendingProviderFocusRef.current = false;
|
|
974
1197
|
focusPayPalSurface();
|
|
975
1198
|
}, [focusPayPalSurface, ready, renderGeneration]);
|
|
976
|
-
const notifyTechnicalFailure = (0,
|
|
1199
|
+
const notifyTechnicalFailure = (0, import_react9.useCallback)((err, options) => {
|
|
977
1200
|
const handler = onTechnicalFailureRef.current;
|
|
978
1201
|
if (handler) {
|
|
979
1202
|
handler("paypal", err, options);
|
|
@@ -1051,7 +1274,7 @@ function DirectPayPalButton({
|
|
|
1051
1274
|
}
|
|
1052
1275
|
return token;
|
|
1053
1276
|
};
|
|
1054
|
-
(0,
|
|
1277
|
+
(0, import_react9.useEffect)(() => {
|
|
1055
1278
|
const handleVisibilityChange = () => {
|
|
1056
1279
|
if (document.visibilityState === "visible") {
|
|
1057
1280
|
scheduleMissingCallbackRecovery();
|
|
@@ -1069,11 +1292,11 @@ function DirectPayPalButton({
|
|
|
1069
1292
|
clearAttemptTimer();
|
|
1070
1293
|
};
|
|
1071
1294
|
}, []);
|
|
1072
|
-
(0,
|
|
1073
|
-
onLoadStateChangeRef.current?.(ready && !failed);
|
|
1295
|
+
(0, import_react9.useEffect)(() => {
|
|
1296
|
+
invokeMerchantCallback(() => onLoadStateChangeRef.current?.(ready && !failed));
|
|
1074
1297
|
}, [ready, failed]);
|
|
1075
1298
|
const normalizedEnv = (0, import_shared4.normalizeGatewayEnvironment)(environment);
|
|
1076
|
-
(0,
|
|
1299
|
+
(0, import_react9.useEffect)(() => {
|
|
1077
1300
|
const maskedClient = clientId ? `${clientId.slice(0, 6)}\u2026(len ${clientId.length})` : "(empty)";
|
|
1078
1301
|
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "(no navigator)";
|
|
1079
1302
|
appendDebug(`mount clientId=${maskedClient} env=${environment ?? "(unset)"}\u2192${normalizedEnv ?? "live"} ccy=${currency} sub=${isSubscription}`);
|
|
@@ -1081,6 +1304,13 @@ function DirectPayPalButton({
|
|
|
1081
1304
|
if (!clientId) {
|
|
1082
1305
|
appendDebug("FAIL: clientId empty \u2014 gateway misconfigured");
|
|
1083
1306
|
setFailed(true);
|
|
1307
|
+
telemetrySource.error({
|
|
1308
|
+
errorCode: "CONFIGURATION_INVALID",
|
|
1309
|
+
stage: "provider_load",
|
|
1310
|
+
provider: "paypal",
|
|
1311
|
+
paymentMethodCategory: "paypal",
|
|
1312
|
+
requestCategory: "provider_sdk"
|
|
1313
|
+
});
|
|
1084
1314
|
console.error("[FloPay] DirectPayPal: clientId empty \u2014 gateway misconfigured");
|
|
1085
1315
|
return;
|
|
1086
1316
|
}
|
|
@@ -1088,8 +1318,33 @@ function DirectPayPalButton({
|
|
|
1088
1318
|
appendDebug("FAIL: containerRef not attached");
|
|
1089
1319
|
return;
|
|
1090
1320
|
}
|
|
1321
|
+
providerStartedAt.current = telemetrySource.startTiming();
|
|
1322
|
+
telemetrySource.log({
|
|
1323
|
+
name: "provider.load.started",
|
|
1324
|
+
stage: "provider_load",
|
|
1325
|
+
provider: "paypal",
|
|
1326
|
+
paymentMethodCategory: "paypal"
|
|
1327
|
+
});
|
|
1091
1328
|
let cancelled = false;
|
|
1092
1329
|
let activeButtons = null;
|
|
1330
|
+
let overlayStartedAt = null;
|
|
1331
|
+
const finishOverlay = () => {
|
|
1332
|
+
if (overlayStartedAt === null) return;
|
|
1333
|
+
telemetrySource.log({
|
|
1334
|
+
name: "provider.overlay.returned",
|
|
1335
|
+
stage: "overlay_return",
|
|
1336
|
+
provider: "paypal",
|
|
1337
|
+
paymentMethodCategory: "paypal"
|
|
1338
|
+
});
|
|
1339
|
+
telemetrySource.performance({
|
|
1340
|
+
stage: "overlay_return",
|
|
1341
|
+
durationMs: telemetrySource.elapsed(overlayStartedAt),
|
|
1342
|
+
durationMode: "buyer",
|
|
1343
|
+
provider: "paypal",
|
|
1344
|
+
paymentMethodCategory: "paypal"
|
|
1345
|
+
});
|
|
1346
|
+
overlayStartedAt = null;
|
|
1347
|
+
};
|
|
1093
1348
|
let rendered = false;
|
|
1094
1349
|
const container = containerRef.current;
|
|
1095
1350
|
let containerObserver = null;
|
|
@@ -1193,7 +1448,7 @@ function DirectPayPalButton({
|
|
|
1193
1448
|
if (cancelled) return;
|
|
1194
1449
|
if (isZoidLifecycleMessage(message)) return;
|
|
1195
1450
|
const friendly = applyFriendlyMessageOverride(message) ?? message;
|
|
1196
|
-
onErrorChangeRef.current?.(friendly);
|
|
1451
|
+
invokeMerchantCallback(() => onErrorChangeRef.current?.(friendly));
|
|
1197
1452
|
};
|
|
1198
1453
|
const markRenderFailed = (message) => {
|
|
1199
1454
|
if (cancelled) return;
|
|
@@ -1202,24 +1457,55 @@ function DirectPayPalButton({
|
|
|
1202
1457
|
return;
|
|
1203
1458
|
}
|
|
1204
1459
|
setFailed(true);
|
|
1460
|
+
if (!message.includes("paypal_ineligible")) {
|
|
1461
|
+
telemetrySource.error({
|
|
1462
|
+
errorCode: "PROVIDER_LOAD_FAILED",
|
|
1463
|
+
stage: "provider_load",
|
|
1464
|
+
provider: "paypal",
|
|
1465
|
+
paymentMethodCategory: "paypal",
|
|
1466
|
+
requestCategory: "provider_sdk"
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1205
1469
|
console.error("[FloPay] DirectPayPal load/render failure:", message);
|
|
1206
1470
|
};
|
|
1207
1471
|
setFailed(false);
|
|
1208
1472
|
const dispatchTokenizedBody = async (body, prepared = beforeClickRef.current) => {
|
|
1209
1473
|
const effectiveSessionId = prepared?.sessionId ?? sessionId;
|
|
1210
1474
|
if (onTokenizedBodyRef.current) {
|
|
1211
|
-
onTokenizedBodyRef.current(body, {
|
|
1475
|
+
await onTokenizedBodyRef.current(body, {
|
|
1212
1476
|
sessionId: effectiveSessionId,
|
|
1213
1477
|
accountPatch: prepared?.accountPatch,
|
|
1214
1478
|
nonce: prepared?.nonce
|
|
1215
1479
|
});
|
|
1216
1480
|
return;
|
|
1217
1481
|
}
|
|
1482
|
+
const processingStartedAt = telemetrySource.startTiming();
|
|
1483
|
+
telemetrySource.log({
|
|
1484
|
+
name: "payment.processing.started",
|
|
1485
|
+
stage: "processing",
|
|
1486
|
+
provider: "paypal",
|
|
1487
|
+
paymentMethodCategory: "paypal"
|
|
1488
|
+
});
|
|
1489
|
+
const finishProcessing = () => {
|
|
1490
|
+
telemetrySource.log({
|
|
1491
|
+
name: "payment.processing.completed",
|
|
1492
|
+
stage: "processing",
|
|
1493
|
+
provider: "paypal",
|
|
1494
|
+
paymentMethodCategory: "paypal"
|
|
1495
|
+
});
|
|
1496
|
+
telemetrySource.performance({
|
|
1497
|
+
stage: "processing",
|
|
1498
|
+
durationMs: telemetrySource.elapsed(processingStartedAt),
|
|
1499
|
+
durationMode: "machine",
|
|
1500
|
+
provider: "paypal",
|
|
1501
|
+
paymentMethodCategory: "paypal"
|
|
1502
|
+
});
|
|
1503
|
+
};
|
|
1218
1504
|
try {
|
|
1219
1505
|
const currentSession = sessionRef.current;
|
|
1220
1506
|
const currentEmail = prepared?.accountPatch?.email ?? emailRef.current;
|
|
1221
1507
|
const effectiveUserId = prepared?.accountPatch?.userId ?? currentSession?.customer?.id ?? currentSession?.accountData?.userId ?? "";
|
|
1222
|
-
const api = new import_js.PaymentAPI(baseUrl);
|
|
1508
|
+
const api = new import_js.PaymentAPI(baseUrl, { telemetry: false });
|
|
1223
1509
|
const response = await api.processPayment(
|
|
1224
1510
|
effectiveUserId,
|
|
1225
1511
|
{
|
|
@@ -1237,31 +1523,71 @@ function DirectPayPalButton({
|
|
|
1237
1523
|
}
|
|
1238
1524
|
);
|
|
1239
1525
|
if (response.ok) {
|
|
1240
|
-
|
|
1526
|
+
finishProcessing();
|
|
1527
|
+
telemetrySource.terminal({
|
|
1528
|
+
outcome: "payment_succeeded",
|
|
1529
|
+
provider: "paypal",
|
|
1530
|
+
paymentMethodCategory: "paypal"
|
|
1531
|
+
});
|
|
1532
|
+
} else {
|
|
1533
|
+
const json = await response.json().catch(() => null);
|
|
1534
|
+
const rawMessage = json?.["message"] ?? "PayPal payment failed.";
|
|
1535
|
+
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
1536
|
+
finishProcessing();
|
|
1537
|
+
if (typeof json?.["declineCode"] === "string") {
|
|
1538
|
+
telemetrySource.terminal({
|
|
1539
|
+
outcome: "payment_declined",
|
|
1540
|
+
provider: "paypal",
|
|
1541
|
+
paymentMethodCategory: "paypal"
|
|
1542
|
+
});
|
|
1543
|
+
} else {
|
|
1544
|
+
telemetrySource.error({
|
|
1545
|
+
errorCode: "PAYMENT_PROCESSING_FAILED",
|
|
1546
|
+
stage: "processing",
|
|
1547
|
+
provider: "paypal",
|
|
1548
|
+
paymentMethodCategory: "paypal",
|
|
1549
|
+
requestCategory: "process_payment",
|
|
1550
|
+
statusClass: response.status >= 500 ? "5xx" : response.status >= 400 ? "4xx" : response.status >= 300 ? "3xx" : "unknown"
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
forwardError(message);
|
|
1554
|
+
invokeMerchantCallback(() => onDeclineRef.current?.(buildDeclineEvent("paypal", message, {
|
|
1555
|
+
code: json?.["code"],
|
|
1556
|
+
declineCode: json?.["declineCode"]
|
|
1557
|
+
})));
|
|
1241
1558
|
return;
|
|
1242
1559
|
}
|
|
1243
|
-
const json = await response.json().catch(() => null);
|
|
1244
|
-
const rawMessage = json?.["message"] ?? "PayPal payment failed.";
|
|
1245
|
-
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
1246
|
-
forwardError(message);
|
|
1247
|
-
onDeclineRef.current?.(buildDeclineEvent("paypal", message, {
|
|
1248
|
-
code: json?.["code"],
|
|
1249
|
-
declineCode: json?.["declineCode"]
|
|
1250
|
-
}));
|
|
1251
1560
|
} catch (err) {
|
|
1561
|
+
finishProcessing();
|
|
1562
|
+
telemetrySource.error({
|
|
1563
|
+
errorCode: "NETWORK_REQUEST_FAILED",
|
|
1564
|
+
stage: "processing",
|
|
1565
|
+
provider: "paypal",
|
|
1566
|
+
paymentMethodCategory: "paypal",
|
|
1567
|
+
requestCategory: "process_payment",
|
|
1568
|
+
statusClass: "network_error"
|
|
1569
|
+
});
|
|
1252
1570
|
const rawMessage = err instanceof Error ? err.message : "PayPal payment failed.";
|
|
1253
1571
|
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
1254
1572
|
forwardError(message);
|
|
1255
|
-
onDeclineRef.current?.(buildDeclineEvent("paypal", message));
|
|
1573
|
+
invokeMerchantCallback(() => onDeclineRef.current?.(buildDeclineEvent("paypal", message)));
|
|
1574
|
+
return;
|
|
1256
1575
|
}
|
|
1576
|
+
invokeMerchantCallback(() => onCompleteRef.current?.({ status: "succeeded", checkoutMethod: "paypal" }));
|
|
1257
1577
|
};
|
|
1258
1578
|
const createPaypalIntent = async (fallbackMessage) => {
|
|
1259
1579
|
const prepared = beforeClickRef.current;
|
|
1260
1580
|
const effectiveSessionId = prepared?.sessionId ?? sessionId;
|
|
1261
1581
|
const effectiveEmail = prepared?.accountPatch?.email ?? emailRef.current;
|
|
1262
|
-
const intentHeaders = { "Content-Type": "application/json" };
|
|
1263
1582
|
const currentNonce = prepared?.nonce ?? nonceRef.current;
|
|
1264
|
-
|
|
1583
|
+
const intentHeaders = intentRequestHeaders(currentNonce);
|
|
1584
|
+
telemetrySource.log({
|
|
1585
|
+
name: "payment.intent.started",
|
|
1586
|
+
stage: "processing",
|
|
1587
|
+
provider: "paypal",
|
|
1588
|
+
paymentMethodCategory: "paypal",
|
|
1589
|
+
requestCategory: "intent_create"
|
|
1590
|
+
});
|
|
1265
1591
|
const response = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
1266
1592
|
method: "POST",
|
|
1267
1593
|
headers: intentHeaders,
|
|
@@ -1280,6 +1606,14 @@ function DirectPayPalButton({
|
|
|
1280
1606
|
if (!id) {
|
|
1281
1607
|
throw new Error(fallbackMessage);
|
|
1282
1608
|
}
|
|
1609
|
+
telemetrySource.log({
|
|
1610
|
+
name: "payment.intent.completed",
|
|
1611
|
+
stage: "processing",
|
|
1612
|
+
provider: "paypal",
|
|
1613
|
+
paymentMethodCategory: "paypal",
|
|
1614
|
+
requestCategory: "intent_create",
|
|
1615
|
+
statusClass: "2xx"
|
|
1616
|
+
});
|
|
1283
1617
|
return id;
|
|
1284
1618
|
};
|
|
1285
1619
|
const effectRenderGeneration = renderGeneration;
|
|
@@ -1314,6 +1648,12 @@ function DirectPayPalButton({
|
|
|
1314
1648
|
if (!cancelled && !paypal?.Buttons) appendDebug("FAIL: namespace missing Buttons factory");
|
|
1315
1649
|
return;
|
|
1316
1650
|
}
|
|
1651
|
+
telemetrySource.log({
|
|
1652
|
+
name: "provider.availability.checked",
|
|
1653
|
+
stage: "provider_ready",
|
|
1654
|
+
provider: "paypal",
|
|
1655
|
+
paymentMethodCategory: "paypal"
|
|
1656
|
+
});
|
|
1317
1657
|
const handleApprove = async (data) => {
|
|
1318
1658
|
if (cancelled || activeRenderGenerationRef.current !== effectRenderGeneration) return;
|
|
1319
1659
|
const token = data.subscriptionID ?? data.orderID ?? "";
|
|
@@ -1322,9 +1662,10 @@ function DirectPayPalButton({
|
|
|
1322
1662
|
if (!finishAttempt(context.generation)) return;
|
|
1323
1663
|
approvalContextByTokenRef.current.delete(token);
|
|
1324
1664
|
attemptContextBySurfaceRef.current.delete(context.surfaceKey);
|
|
1665
|
+
finishOverlay();
|
|
1325
1666
|
try {
|
|
1326
1667
|
setSubmitting(true);
|
|
1327
|
-
onErrorChangeRef.current?.(null);
|
|
1668
|
+
invokeMerchantCallback(() => onErrorChangeRef.current?.(null));
|
|
1328
1669
|
if (!token) {
|
|
1329
1670
|
throw new import_shared4.FloPayError(
|
|
1330
1671
|
"PayPal did not return an approval token.",
|
|
@@ -1374,7 +1715,7 @@ function DirectPayPalButton({
|
|
|
1374
1715
|
return;
|
|
1375
1716
|
}
|
|
1376
1717
|
}
|
|
1377
|
-
onButtonClickRef.current?.("paypal");
|
|
1718
|
+
invokeMerchantCallback(() => onButtonClickRef.current?.("paypal"));
|
|
1378
1719
|
const generation = startAttempt();
|
|
1379
1720
|
const context = {
|
|
1380
1721
|
generation,
|
|
@@ -1384,6 +1725,25 @@ function DirectPayPalButton({
|
|
|
1384
1725
|
beforeClickRef.current = context;
|
|
1385
1726
|
attemptContextBySurfaceRef.current.set(effectRenderGeneration, context);
|
|
1386
1727
|
await actions.resolve();
|
|
1728
|
+
telemetrySource.log({
|
|
1729
|
+
name: "payment.method.selected",
|
|
1730
|
+
stage: "processing",
|
|
1731
|
+
provider: "paypal",
|
|
1732
|
+
paymentMethodCategory: "paypal"
|
|
1733
|
+
});
|
|
1734
|
+
telemetrySource.log({
|
|
1735
|
+
name: "provider.popup.opened",
|
|
1736
|
+
stage: "overlay_open",
|
|
1737
|
+
provider: "paypal",
|
|
1738
|
+
paymentMethodCategory: "paypal"
|
|
1739
|
+
});
|
|
1740
|
+
telemetrySource.log({
|
|
1741
|
+
name: "provider.overlay.opened",
|
|
1742
|
+
stage: "overlay_open",
|
|
1743
|
+
provider: "paypal",
|
|
1744
|
+
paymentMethodCategory: "paypal"
|
|
1745
|
+
});
|
|
1746
|
+
overlayStartedAt = telemetrySource.startTiming();
|
|
1387
1747
|
},
|
|
1388
1748
|
// When the SDK is already holding an order/subscription id from a
|
|
1389
1749
|
// prior backend round-trip (the `paypal_direct_required` retry
|
|
@@ -1396,6 +1756,12 @@ function DirectPayPalButton({
|
|
|
1396
1756
|
const context = attemptContextBySurfaceRef.current.get(effectRenderGeneration) ?? beforeClickRef.current;
|
|
1397
1757
|
if (context) attemptContextBySurfaceRef.current.delete(context.surfaceKey);
|
|
1398
1758
|
beforeClickRef.current = null;
|
|
1759
|
+
finishOverlay();
|
|
1760
|
+
telemetrySource.terminal({
|
|
1761
|
+
outcome: "payment_cancelled",
|
|
1762
|
+
provider: "paypal",
|
|
1763
|
+
paymentMethodCategory: "paypal"
|
|
1764
|
+
});
|
|
1399
1765
|
pendingProviderFocusRef.current = true;
|
|
1400
1766
|
invalidateAttempt({ generation: context?.generation, remount: true, focus: false });
|
|
1401
1767
|
},
|
|
@@ -1411,6 +1777,15 @@ function DirectPayPalButton({
|
|
|
1411
1777
|
finishAttempt(context?.generation);
|
|
1412
1778
|
return;
|
|
1413
1779
|
}
|
|
1780
|
+
finishOverlay();
|
|
1781
|
+
const lower = message.toLowerCase();
|
|
1782
|
+
telemetrySource.error({
|
|
1783
|
+
errorCode: lower.includes("popup") && lower.includes("block") ? "POPUP_BLOCKED" : "PROVIDER_RUNTIME_FAILED",
|
|
1784
|
+
stage: "provider_ready",
|
|
1785
|
+
provider: "paypal",
|
|
1786
|
+
paymentMethodCategory: "paypal",
|
|
1787
|
+
requestCategory: "provider_sdk"
|
|
1788
|
+
});
|
|
1414
1789
|
if (context) attemptContextBySurfaceRef.current.delete(context.surfaceKey);
|
|
1415
1790
|
beforeClickRef.current = null;
|
|
1416
1791
|
invalidateAttempt({ generation: context?.generation, remount: true, showRetry: true, focus: true });
|
|
@@ -1422,6 +1797,12 @@ function DirectPayPalButton({
|
|
|
1422
1797
|
});
|
|
1423
1798
|
const eligible = buttons.isEligible();
|
|
1424
1799
|
appendDebug(`isEligible=${eligible}`);
|
|
1800
|
+
telemetrySource.log({
|
|
1801
|
+
name: "provider.eligibility.checked",
|
|
1802
|
+
stage: "provider_ready",
|
|
1803
|
+
provider: "paypal",
|
|
1804
|
+
paymentMethodCategory: "paypal"
|
|
1805
|
+
});
|
|
1425
1806
|
if (!eligible) {
|
|
1426
1807
|
setReady(false);
|
|
1427
1808
|
markRenderFailed(
|
|
@@ -1493,6 +1874,19 @@ function DirectPayPalButton({
|
|
|
1493
1874
|
activeButtons = typedButtons;
|
|
1494
1875
|
rendered = true;
|
|
1495
1876
|
setReady(true);
|
|
1877
|
+
telemetrySource.log({
|
|
1878
|
+
name: "provider.ready",
|
|
1879
|
+
stage: "provider_ready",
|
|
1880
|
+
provider: "paypal",
|
|
1881
|
+
paymentMethodCategory: "paypal"
|
|
1882
|
+
});
|
|
1883
|
+
telemetrySource.performance({
|
|
1884
|
+
stage: "provider_ready",
|
|
1885
|
+
durationMs: telemetrySource.elapsed(providerStartedAt.current),
|
|
1886
|
+
durationMode: "machine",
|
|
1887
|
+
provider: "paypal",
|
|
1888
|
+
paymentMethodCategory: "paypal"
|
|
1889
|
+
});
|
|
1496
1890
|
}).catch((err) => {
|
|
1497
1891
|
const message = err instanceof Error ? err.message : "PayPal failed to render.";
|
|
1498
1892
|
appendDebug(`render:rejected msg=${message.slice(0, 120)}`);
|
|
@@ -1514,8 +1908,8 @@ function DirectPayPalButton({
|
|
|
1514
1908
|
});
|
|
1515
1909
|
}
|
|
1516
1910
|
};
|
|
1517
|
-
}, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId, renderGeneration]);
|
|
1518
|
-
const debugPanel = debug ? /* @__PURE__ */ (0,
|
|
1911
|
+
}, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId, renderGeneration, telemetrySource]);
|
|
1912
|
+
const debugPanel = debug ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1519
1913
|
"pre",
|
|
1520
1914
|
{
|
|
1521
1915
|
"data-testid": "flopay-direct-paypal-debug",
|
|
@@ -1540,17 +1934,17 @@ ${debugLines.join("\n")}`
|
|
|
1540
1934
|
}
|
|
1541
1935
|
) : null;
|
|
1542
1936
|
if (failed) {
|
|
1543
|
-
return debug ? /* @__PURE__ */ (0,
|
|
1937
|
+
return debug ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: debugPanel }) : null;
|
|
1544
1938
|
}
|
|
1545
1939
|
return (
|
|
1546
1940
|
// Single wrapper so the parent flex container sees exactly one flex item
|
|
1547
1941
|
// (otherwise the fragment's placeholder + container become two siblings
|
|
1548
1942
|
// and any spacing-sensitive layout has to reason about both). The wrapper
|
|
1549
1943
|
// intentionally has no margin/padding so the parent owns all spacing.
|
|
1550
|
-
/* @__PURE__ */ (0,
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
1551
1945
|
debugPanel,
|
|
1552
|
-
/* @__PURE__ */ (0,
|
|
1553
|
-
!ready && /* @__PURE__ */ (0,
|
|
1946
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
|
|
1947
|
+
!ready && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1554
1948
|
"div",
|
|
1555
1949
|
{
|
|
1556
1950
|
"data-testid": "flopay-direct-paypal-placeholder",
|
|
@@ -1564,7 +1958,7 @@ ${debugLines.join("\n")}`
|
|
|
1564
1958
|
}
|
|
1565
1959
|
}
|
|
1566
1960
|
),
|
|
1567
|
-
/* @__PURE__ */ (0,
|
|
1961
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1568
1962
|
"div",
|
|
1569
1963
|
{
|
|
1570
1964
|
ref: containerRef,
|
|
@@ -1581,7 +1975,7 @@ ${debugLines.join("\n")}`
|
|
|
1581
1975
|
renderGeneration
|
|
1582
1976
|
)
|
|
1583
1977
|
] }),
|
|
1584
|
-
showRetryFocusTarget && /* @__PURE__ */ (0,
|
|
1978
|
+
showRetryFocusTarget && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1585
1979
|
"button",
|
|
1586
1980
|
{
|
|
1587
1981
|
ref: focusTargetRef,
|
|
@@ -1595,10 +1989,16 @@ ${debugLines.join("\n")}`
|
|
|
1595
1989
|
] })
|
|
1596
1990
|
);
|
|
1597
1991
|
}
|
|
1992
|
+
function DirectPayPalButton(props) {
|
|
1993
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DirectPayPalButtonImplementation, { ...props });
|
|
1994
|
+
}
|
|
1995
|
+
function InstrumentedDirectPayPalButton(props) {
|
|
1996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DirectPayPalButtonImplementation, { ...props });
|
|
1997
|
+
}
|
|
1598
1998
|
|
|
1599
1999
|
// src/split-card-form.tsx
|
|
1600
2000
|
var import_shared6 = require("@flopay/shared");
|
|
1601
|
-
var
|
|
2001
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1602
2002
|
var STRIPE_RESUME_KEY = "flopay_stripe_resume";
|
|
1603
2003
|
var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
1604
2004
|
var PAYPAL_RESUME_KEY = "flopay_paypal_resume";
|
|
@@ -1713,17 +2113,17 @@ function buildExternalMethodRecoveryMessage(method, popupBlocked) {
|
|
|
1713
2113
|
return popupBlocked ? `${base} Allow pop-ups for this site, then try again.` : base;
|
|
1714
2114
|
}
|
|
1715
2115
|
function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
1716
|
-
const generationRef = (0,
|
|
1717
|
-
const invalidatedGenerationRef = (0,
|
|
1718
|
-
const attemptRef = (0,
|
|
1719
|
-
const clearAttemptTimer = (0,
|
|
2116
|
+
const generationRef = (0, import_react10.useRef)(0);
|
|
2117
|
+
const invalidatedGenerationRef = (0, import_react10.useRef)(null);
|
|
2118
|
+
const attemptRef = (0, import_react10.useRef)(null);
|
|
2119
|
+
const clearAttemptTimer = (0, import_react10.useCallback)((targetAttempt = attemptRef.current) => {
|
|
1720
2120
|
const attempt = targetAttempt;
|
|
1721
2121
|
if (attempt?.timer) {
|
|
1722
2122
|
clearTimeout(attempt.timer);
|
|
1723
2123
|
attempt.timer = null;
|
|
1724
2124
|
}
|
|
1725
2125
|
}, []);
|
|
1726
|
-
const armAttemptTimer = (0,
|
|
2126
|
+
const armAttemptTimer = (0, import_react10.useCallback)((attempt, delayMs) => {
|
|
1727
2127
|
if (typeof document !== "undefined" && document.visibilityState !== "visible") return;
|
|
1728
2128
|
clearAttemptTimer(attempt);
|
|
1729
2129
|
attempt.timer = setTimeout(() => {
|
|
@@ -1738,11 +2138,11 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1738
2138
|
);
|
|
1739
2139
|
}, delayMs);
|
|
1740
2140
|
}, [clearAttemptTimer, onMissingTerminal]);
|
|
1741
|
-
const armRecoveryTimer = (0,
|
|
2141
|
+
const armRecoveryTimer = (0, import_react10.useCallback)((attempt) => {
|
|
1742
2142
|
if (!attempt.yieldedControl) return;
|
|
1743
2143
|
armAttemptTimer(attempt, EXTERNAL_METHOD_CALLBACK_GRACE_MS);
|
|
1744
2144
|
}, [armAttemptTimer]);
|
|
1745
|
-
const startAttempt = (0,
|
|
2145
|
+
const startAttempt = (0, import_react10.useCallback)((method) => {
|
|
1746
2146
|
clearAttemptTimer();
|
|
1747
2147
|
const generation = generationRef.current + 1;
|
|
1748
2148
|
generationRef.current = generation;
|
|
@@ -1751,7 +2151,7 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1751
2151
|
attemptRef.current = attempt;
|
|
1752
2152
|
return generation;
|
|
1753
2153
|
}, [clearAttemptTimer]);
|
|
1754
|
-
const finishAttempt = (0,
|
|
2154
|
+
const finishAttempt = (0, import_react10.useCallback)((generation) => {
|
|
1755
2155
|
const attempt = attemptRef.current;
|
|
1756
2156
|
if (typeof generation === "number" && attempt?.generation !== generation) return false;
|
|
1757
2157
|
clearAttemptTimer(attempt);
|
|
@@ -1761,7 +2161,7 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1761
2161
|
}
|
|
1762
2162
|
return true;
|
|
1763
2163
|
}, [clearAttemptTimer]);
|
|
1764
|
-
const invalidateAttempt = (0,
|
|
2164
|
+
const invalidateAttempt = (0, import_react10.useCallback)((generation) => {
|
|
1765
2165
|
const attempt = attemptRef.current;
|
|
1766
2166
|
const targetGeneration = generation ?? attempt?.generation ?? generationRef.current;
|
|
1767
2167
|
if (!generation || attempt?.generation === generation) {
|
|
@@ -1770,26 +2170,26 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1770
2170
|
}
|
|
1771
2171
|
invalidatedGenerationRef.current = targetGeneration;
|
|
1772
2172
|
}, [clearAttemptTimer]);
|
|
1773
|
-
const isAttemptInvalidated = (0,
|
|
2173
|
+
const isAttemptInvalidated = (0, import_react10.useCallback)(
|
|
1774
2174
|
(generation) => invalidatedGenerationRef.current === (generation ?? generationRef.current),
|
|
1775
2175
|
[]
|
|
1776
2176
|
);
|
|
1777
|
-
const isAttemptCurrent = (0,
|
|
2177
|
+
const isAttemptCurrent = (0, import_react10.useCallback)(
|
|
1778
2178
|
(generation) => attemptRef.current?.generation === generation && invalidatedGenerationRef.current !== generation,
|
|
1779
2179
|
[]
|
|
1780
2180
|
);
|
|
1781
|
-
const scheduleRecoveryIfReturned = (0,
|
|
2181
|
+
const scheduleRecoveryIfReturned = (0, import_react10.useCallback)(() => {
|
|
1782
2182
|
const attempt = attemptRef.current;
|
|
1783
2183
|
if (!attempt) return;
|
|
1784
2184
|
armRecoveryTimer(attempt);
|
|
1785
2185
|
}, [armRecoveryTimer]);
|
|
1786
|
-
const markAttemptYieldedControl = (0,
|
|
2186
|
+
const markAttemptYieldedControl = (0, import_react10.useCallback)(() => {
|
|
1787
2187
|
const attempt = attemptRef.current;
|
|
1788
2188
|
if (!attempt) return;
|
|
1789
2189
|
attempt.yieldedControl = true;
|
|
1790
2190
|
clearAttemptTimer(attempt);
|
|
1791
2191
|
}, [clearAttemptTimer]);
|
|
1792
|
-
(0,
|
|
2192
|
+
(0, import_react10.useEffect)(() => {
|
|
1793
2193
|
const handleVisibilityChange = () => {
|
|
1794
2194
|
if (document.visibilityState === "visible") {
|
|
1795
2195
|
scheduleRecoveryIfReturned();
|
|
@@ -1831,7 +2231,7 @@ function normalizeBeforeButtonClickError(method, err) {
|
|
|
1831
2231
|
);
|
|
1832
2232
|
}
|
|
1833
2233
|
function FloPayKeyframes() {
|
|
1834
|
-
return /* @__PURE__ */ (0,
|
|
2234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: FLOPAY_KEYFRAMES });
|
|
1835
2235
|
}
|
|
1836
2236
|
function toCssSize(value) {
|
|
1837
2237
|
if (typeof value === "number") return `${value}px`;
|
|
@@ -1853,8 +2253,8 @@ function ExpressCheckoutReadySwap({
|
|
|
1853
2253
|
children
|
|
1854
2254
|
}) {
|
|
1855
2255
|
if (state === "unavailable" || state === "load_error") return null;
|
|
1856
|
-
return /* @__PURE__ */ (0,
|
|
1857
|
-
/* @__PURE__ */ (0,
|
|
2256
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
2257
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1858
2258
|
"div",
|
|
1859
2259
|
{
|
|
1860
2260
|
"data-testid": placeholderTestId,
|
|
@@ -1873,7 +2273,7 @@ function ExpressCheckoutReadySwap({
|
|
|
1873
2273
|
}
|
|
1874
2274
|
}
|
|
1875
2275
|
),
|
|
1876
|
-
/* @__PURE__ */ (0,
|
|
2276
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1877
2277
|
"div",
|
|
1878
2278
|
{
|
|
1879
2279
|
style: {
|
|
@@ -1891,9 +2291,9 @@ function ExpressCheckoutReadySwap({
|
|
|
1891
2291
|
function isExpressCheckoutRowVisible(state) {
|
|
1892
2292
|
return state !== "unavailable" && state !== "load_error";
|
|
1893
2293
|
}
|
|
1894
|
-
var SplitCardForm = (0,
|
|
2294
|
+
var SplitCardForm = (0, import_react10.forwardRef)(
|
|
1895
2295
|
function SplitCardForm2(props, ref) {
|
|
1896
|
-
return /* @__PURE__ */ (0,
|
|
2296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
|
|
1897
2297
|
}
|
|
1898
2298
|
);
|
|
1899
2299
|
function PayPalButtonInner({
|
|
@@ -1911,20 +2311,21 @@ function PayPalButtonInner({
|
|
|
1911
2311
|
onLoadStateChange,
|
|
1912
2312
|
placeholderBorderRadius
|
|
1913
2313
|
}) {
|
|
2314
|
+
const flopay = useFloPay();
|
|
1914
2315
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
1915
2316
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
1916
|
-
const [loadState, setLoadState] = (0,
|
|
1917
|
-
(0,
|
|
2317
|
+
const [loadState, setLoadState] = (0, import_react10.useState)("loading");
|
|
2318
|
+
(0, import_react10.useEffect)(() => {
|
|
1918
2319
|
onLoadStateChange?.(loadState);
|
|
1919
2320
|
}, [loadState, onLoadStateChange]);
|
|
1920
|
-
const [submitting, setSubmitting] = (0,
|
|
1921
|
-
const paypalResumeAttempted = (0,
|
|
1922
|
-
const focusTargetRef = (0,
|
|
1923
|
-
const recoveryActionRef = (0,
|
|
1924
|
-
const [surfaceKey, setSurfaceKey] = (0,
|
|
1925
|
-
const [showRecoveryAction, setShowRecoveryAction] = (0,
|
|
1926
|
-
const pendingProviderFocusRef = (0,
|
|
1927
|
-
const attemptContextBySurfaceRef = (0,
|
|
2321
|
+
const [submitting, setSubmitting] = (0, import_react10.useState)(false);
|
|
2322
|
+
const paypalResumeAttempted = (0, import_react10.useRef)(false);
|
|
2323
|
+
const focusTargetRef = (0, import_react10.useRef)(null);
|
|
2324
|
+
const recoveryActionRef = (0, import_react10.useRef)(null);
|
|
2325
|
+
const [surfaceKey, setSurfaceKey] = (0, import_react10.useState)(0);
|
|
2326
|
+
const [showRecoveryAction, setShowRecoveryAction] = (0, import_react10.useState)(false);
|
|
2327
|
+
const pendingProviderFocusRef = (0, import_react10.useRef)(false);
|
|
2328
|
+
const attemptContextBySurfaceRef = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
|
|
1928
2329
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
1929
2330
|
const {
|
|
1930
2331
|
startAttempt,
|
|
@@ -1940,35 +2341,35 @@ function PayPalButtonInner({
|
|
|
1940
2341
|
setShowRecoveryAction(true);
|
|
1941
2342
|
setSurfaceKey((key) => key + 1);
|
|
1942
2343
|
});
|
|
1943
|
-
(0,
|
|
2344
|
+
(0, import_react10.useEffect)(() => {
|
|
1944
2345
|
if (showRecoveryAction) recoveryActionRef.current?.focus();
|
|
1945
2346
|
}, [showRecoveryAction, surfaceKey]);
|
|
1946
|
-
const resetSurface = (0,
|
|
2347
|
+
const resetSurface = (0, import_react10.useCallback)(() => {
|
|
1947
2348
|
setSurfaceKey((key) => key + 1);
|
|
1948
2349
|
}, []);
|
|
1949
|
-
const recoverTechnicalFailure = (0,
|
|
2350
|
+
const recoverTechnicalFailure = (0, import_react10.useCallback)((err, code, generation) => {
|
|
1950
2351
|
invalidateAttempt(generation);
|
|
1951
2352
|
onTechnicalFailure?.("paypal", err, { code, popupBlocked: isPopupBlockedError(err) });
|
|
1952
2353
|
setShowRecoveryAction(true);
|
|
1953
2354
|
resetSurface();
|
|
1954
2355
|
}, [invalidateAttempt, onTechnicalFailure, resetSurface]);
|
|
1955
|
-
const focusProviderSurface = (0,
|
|
2356
|
+
const focusProviderSurface = (0, import_react10.useCallback)(() => {
|
|
1956
2357
|
window.setTimeout(() => {
|
|
1957
2358
|
const target = focusTargetRef.current?.querySelector("iframe");
|
|
1958
2359
|
(target ?? focusTargetRef.current)?.focus();
|
|
1959
2360
|
}, 0);
|
|
1960
2361
|
}, []);
|
|
1961
|
-
(0,
|
|
2362
|
+
(0, import_react10.useEffect)(() => {
|
|
1962
2363
|
if (!pendingProviderFocusRef.current) return;
|
|
1963
2364
|
pendingProviderFocusRef.current = false;
|
|
1964
2365
|
focusProviderSurface();
|
|
1965
2366
|
}, [focusProviderSurface, surfaceKey]);
|
|
1966
|
-
const handleRecoveryActionClick = (0,
|
|
2367
|
+
const handleRecoveryActionClick = (0, import_react10.useCallback)(() => {
|
|
1967
2368
|
setShowRecoveryAction(false);
|
|
1968
2369
|
onErrorChange?.(null);
|
|
1969
2370
|
focusProviderSurface();
|
|
1970
2371
|
}, [focusProviderSurface, onErrorChange]);
|
|
1971
|
-
(0,
|
|
2372
|
+
(0, import_react10.useEffect)(() => {
|
|
1972
2373
|
if (!stripe || paypalResumeAttempted.current) return;
|
|
1973
2374
|
const params = new URLSearchParams(window.location.search);
|
|
1974
2375
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -2034,7 +2435,7 @@ function PayPalButtonInner({
|
|
|
2034
2435
|
}
|
|
2035
2436
|
})();
|
|
2036
2437
|
}, [stripe, onTokenizedBody, onErrorChange, onDecline]);
|
|
2037
|
-
const handlePayPalClick = (0,
|
|
2438
|
+
const handlePayPalClick = (0, import_react10.useCallback)(async (event) => {
|
|
2038
2439
|
if (isProcessing || submitting) {
|
|
2039
2440
|
event.reject();
|
|
2040
2441
|
return;
|
|
@@ -2056,7 +2457,7 @@ function PayPalButtonInner({
|
|
|
2056
2457
|
onButtonClick?.("paypal");
|
|
2057
2458
|
event.resolve();
|
|
2058
2459
|
}, [attemptContextBySurfaceRef, isProcessing, onButtonClick, runBeforeButtonClick, startAttempt, submitting, surfaceKey]);
|
|
2059
|
-
const handlePayPalConfirm = (0,
|
|
2460
|
+
const handlePayPalConfirm = (0, import_react10.useCallback)(async (event) => {
|
|
2060
2461
|
if (!stripe || !elements) return;
|
|
2061
2462
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
2062
2463
|
if (attemptContext && !isAttemptCurrent(attemptContext.generation)) {
|
|
@@ -2096,8 +2497,7 @@ function PayPalButtonInner({
|
|
|
2096
2497
|
event.paymentFailed({ reason: "fail" });
|
|
2097
2498
|
return;
|
|
2098
2499
|
}
|
|
2099
|
-
const intentHeaders =
|
|
2100
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
2500
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2101
2501
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2102
2502
|
method: "POST",
|
|
2103
2503
|
headers: intentHeaders,
|
|
@@ -2188,14 +2588,14 @@ function PayPalButtonInner({
|
|
|
2188
2588
|
setSubmitting(false);
|
|
2189
2589
|
}
|
|
2190
2590
|
}, [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick, recoverTechnicalFailure, finishAttempt, isAttemptCurrent, isAttemptInvalidated, surfaceKey]);
|
|
2191
|
-
return /* @__PURE__ */ (0,
|
|
2192
|
-
/* @__PURE__ */ (0,
|
|
2591
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2592
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2193
2593
|
ExpressCheckoutReadySwap,
|
|
2194
2594
|
{
|
|
2195
2595
|
state: loadState,
|
|
2196
2596
|
placeholderTestId: "flopay-paypal-placeholder",
|
|
2197
2597
|
borderRadius: placeholderBorderRadius,
|
|
2198
|
-
children: /* @__PURE__ */ (0,
|
|
2598
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2199
2599
|
"div",
|
|
2200
2600
|
{
|
|
2201
2601
|
ref: focusTargetRef,
|
|
@@ -2204,7 +2604,7 @@ function PayPalButtonInner({
|
|
|
2204
2604
|
"aria-label": "PayPal payment method",
|
|
2205
2605
|
style: { borderRadius: 8, outlineOffset: 4 },
|
|
2206
2606
|
children: [
|
|
2207
|
-
showRecoveryAction && /* @__PURE__ */ (0,
|
|
2607
|
+
showRecoveryAction && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2208
2608
|
"button",
|
|
2209
2609
|
{
|
|
2210
2610
|
ref: recoveryActionRef,
|
|
@@ -2215,7 +2615,7 @@ function PayPalButtonInner({
|
|
|
2215
2615
|
children: "Try PayPal again"
|
|
2216
2616
|
}
|
|
2217
2617
|
),
|
|
2218
|
-
/* @__PURE__ */ (0,
|
|
2618
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2219
2619
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
2220
2620
|
{
|
|
2221
2621
|
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
@@ -2225,6 +2625,11 @@ function PayPalButtonInner({
|
|
|
2225
2625
|
onCancel: () => {
|
|
2226
2626
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
2227
2627
|
attemptContextBySurfaceRef.current.delete(surfaceKey);
|
|
2628
|
+
getFloPayTelemetryBridge(flopay)?.terminal({
|
|
2629
|
+
outcome: "payment_cancelled",
|
|
2630
|
+
provider: "paypal",
|
|
2631
|
+
paymentMethodCategory: "paypal"
|
|
2632
|
+
});
|
|
2228
2633
|
invalidateAttempt(attemptContext?.generation);
|
|
2229
2634
|
setShowRecoveryAction(false);
|
|
2230
2635
|
pendingProviderFocusRef.current = true;
|
|
@@ -2250,7 +2655,7 @@ function PayPalButtonInner({
|
|
|
2250
2655
|
)
|
|
2251
2656
|
}
|
|
2252
2657
|
),
|
|
2253
|
-
submitting && /* @__PURE__ */ (0,
|
|
2658
|
+
submitting && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: "processing" })
|
|
2254
2659
|
] });
|
|
2255
2660
|
}
|
|
2256
2661
|
function WalletButtonInner({
|
|
@@ -2268,23 +2673,24 @@ function WalletButtonInner({
|
|
|
2268
2673
|
onLoadStateChange,
|
|
2269
2674
|
placeholderBorderRadius
|
|
2270
2675
|
}) {
|
|
2676
|
+
const flopay = useFloPay();
|
|
2271
2677
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
2272
2678
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
2273
|
-
const [loadState, setLoadState] = (0,
|
|
2274
|
-
(0,
|
|
2679
|
+
const [loadState, setLoadState] = (0, import_react10.useState)("loading");
|
|
2680
|
+
(0, import_react10.useEffect)(() => {
|
|
2275
2681
|
onLoadStateChange?.(loadState);
|
|
2276
2682
|
}, [loadState, onLoadStateChange]);
|
|
2277
|
-
const [submitting, setSubmitting] = (0,
|
|
2683
|
+
const [submitting, setSubmitting] = (0, import_react10.useState)(false);
|
|
2278
2684
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2279
|
-
const focusTargetRef = (0,
|
|
2280
|
-
const recoveryActionRef = (0,
|
|
2281
|
-
const [surfaceKey, setSurfaceKey] = (0,
|
|
2282
|
-
const [showRecoveryAction, setShowRecoveryAction] = (0,
|
|
2283
|
-
const [recoveryActionMethod, setRecoveryActionMethod] = (0,
|
|
2284
|
-
const pendingProviderFocusRef = (0,
|
|
2285
|
-
const lastWalletProviderMethodRef = (0,
|
|
2286
|
-
const lastWalletMethodRef = (0,
|
|
2287
|
-
const attemptContextBySurfaceRef = (0,
|
|
2685
|
+
const focusTargetRef = (0, import_react10.useRef)(null);
|
|
2686
|
+
const recoveryActionRef = (0, import_react10.useRef)(null);
|
|
2687
|
+
const [surfaceKey, setSurfaceKey] = (0, import_react10.useState)(0);
|
|
2688
|
+
const [showRecoveryAction, setShowRecoveryAction] = (0, import_react10.useState)(false);
|
|
2689
|
+
const [recoveryActionMethod, setRecoveryActionMethod] = (0, import_react10.useState)("google_pay");
|
|
2690
|
+
const pendingProviderFocusRef = (0, import_react10.useRef)(false);
|
|
2691
|
+
const lastWalletProviderMethodRef = (0, import_react10.useRef)("google_pay");
|
|
2692
|
+
const lastWalletMethodRef = (0, import_react10.useRef)("google_pay");
|
|
2693
|
+
const attemptContextBySurfaceRef = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
|
|
2288
2694
|
const {
|
|
2289
2695
|
startAttempt,
|
|
2290
2696
|
finishAttempt,
|
|
@@ -2300,36 +2706,36 @@ function WalletButtonInner({
|
|
|
2300
2706
|
setShowRecoveryAction(true);
|
|
2301
2707
|
setSurfaceKey((key) => key + 1);
|
|
2302
2708
|
});
|
|
2303
|
-
(0,
|
|
2709
|
+
(0, import_react10.useEffect)(() => {
|
|
2304
2710
|
if (showRecoveryAction) recoveryActionRef.current?.focus();
|
|
2305
2711
|
}, [showRecoveryAction, surfaceKey]);
|
|
2306
|
-
const resetSurface = (0,
|
|
2712
|
+
const resetSurface = (0, import_react10.useCallback)(() => {
|
|
2307
2713
|
setSurfaceKey((key) => key + 1);
|
|
2308
2714
|
}, []);
|
|
2309
|
-
const recoverTechnicalFailure = (0,
|
|
2715
|
+
const recoverTechnicalFailure = (0, import_react10.useCallback)((method, err, code, generation) => {
|
|
2310
2716
|
invalidateAttempt(generation);
|
|
2311
2717
|
onTechnicalFailure?.(method, err, { code, popupBlocked: isPopupBlockedError(err) });
|
|
2312
2718
|
setRecoveryActionMethod(method);
|
|
2313
2719
|
setShowRecoveryAction(true);
|
|
2314
2720
|
resetSurface();
|
|
2315
2721
|
}, [invalidateAttempt, onTechnicalFailure, resetSurface]);
|
|
2316
|
-
const focusProviderSurface = (0,
|
|
2722
|
+
const focusProviderSurface = (0, import_react10.useCallback)(() => {
|
|
2317
2723
|
window.setTimeout(() => {
|
|
2318
2724
|
const target = focusTargetRef.current?.querySelector("iframe");
|
|
2319
2725
|
(target ?? focusTargetRef.current)?.focus();
|
|
2320
2726
|
}, 0);
|
|
2321
2727
|
}, []);
|
|
2322
|
-
(0,
|
|
2728
|
+
(0, import_react10.useEffect)(() => {
|
|
2323
2729
|
if (!pendingProviderFocusRef.current) return;
|
|
2324
2730
|
pendingProviderFocusRef.current = false;
|
|
2325
2731
|
focusProviderSurface();
|
|
2326
2732
|
}, [focusProviderSurface, surfaceKey]);
|
|
2327
|
-
const handleRecoveryActionClick = (0,
|
|
2733
|
+
const handleRecoveryActionClick = (0, import_react10.useCallback)(() => {
|
|
2328
2734
|
setShowRecoveryAction(false);
|
|
2329
2735
|
onErrorChange?.(null);
|
|
2330
2736
|
focusProviderSurface();
|
|
2331
2737
|
}, [focusProviderSurface, onErrorChange]);
|
|
2332
|
-
const handleWalletConfirm = (0,
|
|
2738
|
+
const handleWalletConfirm = (0, import_react10.useCallback)(
|
|
2333
2739
|
async (event) => {
|
|
2334
2740
|
if (!stripe || !elements) return;
|
|
2335
2741
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
@@ -2376,8 +2782,7 @@ function WalletButtonInner({
|
|
|
2376
2782
|
if (!effectiveSessionId || !effectiveEmail) {
|
|
2377
2783
|
throw new Error("Missing sessionId or email for wallet payment");
|
|
2378
2784
|
}
|
|
2379
|
-
const intentHeaders =
|
|
2380
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
2785
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2381
2786
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2382
2787
|
method: "POST",
|
|
2383
2788
|
headers: intentHeaders,
|
|
@@ -2432,7 +2837,7 @@ function WalletButtonInner({
|
|
|
2432
2837
|
},
|
|
2433
2838
|
[stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick, recoverTechnicalFailure, finishAttempt, isAttemptCurrent, isAttemptInvalidated, surfaceKey]
|
|
2434
2839
|
);
|
|
2435
|
-
const expressMethodMap = (0,
|
|
2840
|
+
const expressMethodMap = (0, import_react10.useMemo)(() => {
|
|
2436
2841
|
const allKeys = ["applePay", "googlePay", "paypal", "link", "amazonPay", "klarna"];
|
|
2437
2842
|
const alwaysCapable = /* @__PURE__ */ new Set(["applePay", "googlePay"]);
|
|
2438
2843
|
const enabledKeys = new Set(expressMethods.map(import_shared5.stripeExpressMethodToOptionKey));
|
|
@@ -2446,18 +2851,18 @@ function WalletButtonInner({
|
|
|
2446
2851
|
}
|
|
2447
2852
|
return out;
|
|
2448
2853
|
}, [expressMethods]);
|
|
2449
|
-
const availableMethodKeys = (0,
|
|
2854
|
+
const availableMethodKeys = (0, import_react10.useMemo)(
|
|
2450
2855
|
() => expressMethods.map(import_shared5.stripeExpressMethodToOptionKey),
|
|
2451
2856
|
[expressMethods]
|
|
2452
2857
|
);
|
|
2453
|
-
return /* @__PURE__ */ (0,
|
|
2454
|
-
/* @__PURE__ */ (0,
|
|
2858
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2859
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2455
2860
|
ExpressCheckoutReadySwap,
|
|
2456
2861
|
{
|
|
2457
2862
|
state: loadState,
|
|
2458
2863
|
placeholderTestId: "flopay-wallet-placeholder",
|
|
2459
2864
|
borderRadius: placeholderBorderRadius,
|
|
2460
|
-
children: /* @__PURE__ */ (0,
|
|
2865
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2461
2866
|
"div",
|
|
2462
2867
|
{
|
|
2463
2868
|
ref: focusTargetRef,
|
|
@@ -2466,7 +2871,7 @@ function WalletButtonInner({
|
|
|
2466
2871
|
"aria-label": "Wallet payment methods",
|
|
2467
2872
|
style: { borderRadius: 8, outlineOffset: 4 },
|
|
2468
2873
|
children: [
|
|
2469
|
-
showRecoveryAction && /* @__PURE__ */ (0,
|
|
2874
|
+
showRecoveryAction && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2470
2875
|
"button",
|
|
2471
2876
|
{
|
|
2472
2877
|
ref: recoveryActionRef,
|
|
@@ -2481,7 +2886,7 @@ function WalletButtonInner({
|
|
|
2481
2886
|
]
|
|
2482
2887
|
}
|
|
2483
2888
|
),
|
|
2484
|
-
/* @__PURE__ */ (0,
|
|
2889
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2485
2890
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
2486
2891
|
{
|
|
2487
2892
|
onReady: (event) => {
|
|
@@ -2489,6 +2894,13 @@ function WalletButtonInner({
|
|
|
2489
2894
|
},
|
|
2490
2895
|
onLoadError: (_event) => {
|
|
2491
2896
|
setLoadState("load_error");
|
|
2897
|
+
getFloPayTelemetryBridge(flopay)?.error({
|
|
2898
|
+
errorCode: "PROVIDER_LOAD_FAILED",
|
|
2899
|
+
stage: "provider_load",
|
|
2900
|
+
provider: "stripe",
|
|
2901
|
+
paymentMethodCategory: "wallet",
|
|
2902
|
+
requestCategory: "provider_sdk"
|
|
2903
|
+
});
|
|
2492
2904
|
},
|
|
2493
2905
|
onClick: async (event) => {
|
|
2494
2906
|
lastWalletProviderMethodRef.current = event.expressPaymentType;
|
|
@@ -2515,6 +2927,11 @@ function WalletButtonInner({
|
|
|
2515
2927
|
onCancel: () => {
|
|
2516
2928
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
2517
2929
|
attemptContextBySurfaceRef.current.delete(surfaceKey);
|
|
2930
|
+
getFloPayTelemetryBridge(flopay)?.terminal({
|
|
2931
|
+
outcome: "payment_cancelled",
|
|
2932
|
+
provider: "stripe",
|
|
2933
|
+
paymentMethodCategory: "wallet"
|
|
2934
|
+
});
|
|
2518
2935
|
invalidateAttempt(attemptContext?.generation);
|
|
2519
2936
|
setShowRecoveryAction(false);
|
|
2520
2937
|
pendingProviderFocusRef.current = true;
|
|
@@ -2533,7 +2950,7 @@ function WalletButtonInner({
|
|
|
2533
2950
|
)
|
|
2534
2951
|
}
|
|
2535
2952
|
),
|
|
2536
|
-
submitting && /* @__PURE__ */ (0,
|
|
2953
|
+
submitting && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: "processing" })
|
|
2537
2954
|
] });
|
|
2538
2955
|
}
|
|
2539
2956
|
function StripeMethodButton({
|
|
@@ -2551,10 +2968,11 @@ function StripeMethodButton({
|
|
|
2551
2968
|
fontFamily
|
|
2552
2969
|
}) {
|
|
2553
2970
|
const brand = (0, import_shared5.resolveStripeMethodBrandVariant)(method, themeId);
|
|
2971
|
+
const vendoredLogoUrl = PAYMENT_METHOD_LOGO_URLS[method];
|
|
2554
2972
|
const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
|
|
2555
2973
|
const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
|
|
2556
2974
|
const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
|
|
2557
|
-
return /* @__PURE__ */ (0,
|
|
2975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2558
2976
|
"button",
|
|
2559
2977
|
{
|
|
2560
2978
|
type: "button",
|
|
@@ -2601,9 +3019,9 @@ function StripeMethodButton({
|
|
|
2601
3019
|
// Pulse-skeleton parity with the wallet ECE: no spinner, just the
|
|
2602
3020
|
// status text on top of the pulsing background. Keeps the loading
|
|
2603
3021
|
// affordance shape-equivalent across both kinds of tile.
|
|
2604
|
-
/* @__PURE__ */ (0,
|
|
2605
|
-
) : /* @__PURE__ */ (0,
|
|
2606
|
-
/* @__PURE__ */ (0,
|
|
3022
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { margin: "0 auto" }, children: `Connecting to ${(0, import_shared5.getStripeMethodDisplayName)(method)}\u2026` })
|
|
3023
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3024
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2607
3025
|
"span",
|
|
2608
3026
|
{
|
|
2609
3027
|
style: {
|
|
@@ -2616,15 +3034,36 @@ function StripeMethodButton({
|
|
|
2616
3034
|
gap: (0, import_shared5.hasVendoredStripeMethodLogo)(method) ? 8 : 0
|
|
2617
3035
|
},
|
|
2618
3036
|
children: [
|
|
2619
|
-
|
|
3037
|
+
vendoredLogoUrl ? (
|
|
3038
|
+
// Vendored brand logo — an <img> asset (not inline SVG) so its
|
|
3039
|
+
// bytes ship as a sibling file, out of the JS bundle. 3:2 box
|
|
3040
|
+
// matching the datatrans logos' 120×80 viewBox; each ships its own
|
|
3041
|
+
// white rounded-rect background so it stays legible on any tile.
|
|
3042
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3043
|
+
"img",
|
|
3044
|
+
{
|
|
3045
|
+
src: vendoredLogoUrl,
|
|
3046
|
+
alt: "",
|
|
3047
|
+
"aria-hidden": "true",
|
|
3048
|
+
loading: "lazy",
|
|
3049
|
+
decoding: "async",
|
|
3050
|
+
width: 30,
|
|
3051
|
+
height: 20,
|
|
3052
|
+
style: {
|
|
3053
|
+
width: 30,
|
|
3054
|
+
height: 20,
|
|
3055
|
+
flexShrink: 0,
|
|
3056
|
+
borderRadius: 3,
|
|
3057
|
+
objectFit: "contain",
|
|
3058
|
+
display: "inline-flex"
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
)
|
|
3062
|
+
) : brand?.logoSvg ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2620
3063
|
"span",
|
|
2621
3064
|
{
|
|
2622
3065
|
"aria-hidden": "true",
|
|
2623
3066
|
style: {
|
|
2624
|
-
// 3:2 box matching the vendored datatrans logos' 120×80
|
|
2625
|
-
// viewBox. Each logo ships with its own white rounded-rect
|
|
2626
|
-
// background baked in, so the mark stays legible on any
|
|
2627
|
-
// brand-coloured tile without an extra chip wrapper here.
|
|
2628
3067
|
width: 30,
|
|
2629
3068
|
height: 20,
|
|
2630
3069
|
flexShrink: 0,
|
|
@@ -2634,12 +3073,12 @@ function StripeMethodButton({
|
|
|
2634
3073
|
},
|
|
2635
3074
|
dangerouslySetInnerHTML: { __html: brand.logoSvg }
|
|
2636
3075
|
}
|
|
2637
|
-
),
|
|
2638
|
-
/* @__PURE__ */ (0,
|
|
3076
|
+
) : null,
|
|
3077
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
|
|
2639
3078
|
]
|
|
2640
3079
|
}
|
|
2641
3080
|
),
|
|
2642
|
-
hasNextStep && /* @__PURE__ */ (0,
|
|
3081
|
+
hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2643
3082
|
"svg",
|
|
2644
3083
|
{
|
|
2645
3084
|
width: "14",
|
|
@@ -2659,7 +3098,7 @@ function StripeMethodButton({
|
|
|
2659
3098
|
opacity: 0.7
|
|
2660
3099
|
},
|
|
2661
3100
|
"aria-hidden": "true",
|
|
2662
|
-
children: /* @__PURE__ */ (0,
|
|
3101
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M9 18l6-6-6-6" })
|
|
2663
3102
|
}
|
|
2664
3103
|
)
|
|
2665
3104
|
] })
|
|
@@ -2685,14 +3124,15 @@ function StripeMethodInlineForm({
|
|
|
2685
3124
|
submitButtonStyle,
|
|
2686
3125
|
errorText
|
|
2687
3126
|
}) {
|
|
3127
|
+
const flopay = useFloPay();
|
|
2688
3128
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
2689
3129
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
2690
|
-
const [submitting, setSubmitting] = (0,
|
|
2691
|
-
const submittingRef = (0,
|
|
2692
|
-
const [isMethodComplete, setIsMethodComplete] = (0,
|
|
2693
|
-
const [loadState, setLoadState] = (0,
|
|
3130
|
+
const [submitting, setSubmitting] = (0, import_react10.useState)(false);
|
|
3131
|
+
const submittingRef = (0, import_react10.useRef)(false);
|
|
3132
|
+
const [isMethodComplete, setIsMethodComplete] = (0, import_react10.useState)(false);
|
|
3133
|
+
const [loadState, setLoadState] = (0, import_react10.useState)("loading");
|
|
2694
3134
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2695
|
-
const handlePay = (0,
|
|
3135
|
+
const handlePay = (0, import_react10.useCallback)(async () => {
|
|
2696
3136
|
if (!stripe || !elements || isProcessing || submittingRef.current || !isMethodComplete) return;
|
|
2697
3137
|
submittingRef.current = true;
|
|
2698
3138
|
setSubmitting(true);
|
|
@@ -2722,8 +3162,7 @@ function StripeMethodInlineForm({
|
|
|
2722
3162
|
if (!effectiveSessionId || !effectiveEmail) {
|
|
2723
3163
|
throw new Error("Missing sessionId or email for payment.");
|
|
2724
3164
|
}
|
|
2725
|
-
const intentHeaders =
|
|
2726
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
3165
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2727
3166
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2728
3167
|
method: "POST",
|
|
2729
3168
|
headers: intentHeaders,
|
|
@@ -2777,9 +3216,8 @@ function StripeMethodInlineForm({
|
|
|
2777
3216
|
onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
|
|
2778
3217
|
return;
|
|
2779
3218
|
}
|
|
2780
|
-
const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
|
|
2781
3219
|
const piStatus = paymentIntent?.status;
|
|
2782
|
-
if (!
|
|
3220
|
+
if (!isSuccessfulPaymentIntentStatus(piStatus)) {
|
|
2783
3221
|
if (typeof window !== "undefined") {
|
|
2784
3222
|
try {
|
|
2785
3223
|
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
@@ -2832,12 +3270,21 @@ function StripeMethodInlineForm({
|
|
|
2832
3270
|
onDecline
|
|
2833
3271
|
]);
|
|
2834
3272
|
void onCancel;
|
|
2835
|
-
return /* @__PURE__ */ (0,
|
|
2836
|
-
/* @__PURE__ */ (0,
|
|
3273
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
|
|
3274
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2837
3275
|
import_react_stripe_js.PaymentElement,
|
|
2838
3276
|
{
|
|
2839
3277
|
onReady: () => setLoadState("ready"),
|
|
2840
|
-
onLoadError: () =>
|
|
3278
|
+
onLoadError: () => {
|
|
3279
|
+
setLoadState("load_error");
|
|
3280
|
+
getFloPayTelemetryBridge(flopay)?.error({
|
|
3281
|
+
errorCode: "PROVIDER_LOAD_FAILED",
|
|
3282
|
+
stage: "provider_load",
|
|
3283
|
+
provider: "stripe",
|
|
3284
|
+
paymentMethodCategory: "apm",
|
|
3285
|
+
requestCategory: "provider_sdk"
|
|
3286
|
+
});
|
|
3287
|
+
},
|
|
2841
3288
|
onChange: (event) => {
|
|
2842
3289
|
const evRecord = event;
|
|
2843
3290
|
setIsMethodComplete(!!evRecord.complete);
|
|
@@ -2853,7 +3300,7 @@ function StripeMethodInlineForm({
|
|
|
2853
3300
|
}
|
|
2854
3301
|
}
|
|
2855
3302
|
),
|
|
2856
|
-
/* @__PURE__ */ (0,
|
|
3303
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2857
3304
|
"button",
|
|
2858
3305
|
{
|
|
2859
3306
|
type: "button",
|
|
@@ -2880,22 +3327,7 @@ function StripeMethodInlineForm({
|
|
|
2880
3327
|
children: submitting ? "Processing\u2026" : `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(method)}`
|
|
2881
3328
|
}
|
|
2882
3329
|
),
|
|
2883
|
-
errorText && /* @__PURE__ */ (0,
|
|
2884
|
-
margin: "0.75rem 0 0",
|
|
2885
|
-
padding: "0.625rem 0.875rem",
|
|
2886
|
-
background: "#FEF2F2",
|
|
2887
|
-
border: "1px solid #FECACA",
|
|
2888
|
-
borderRadius: "8px",
|
|
2889
|
-
color: "#991B1B",
|
|
2890
|
-
fontSize: "0.85rem",
|
|
2891
|
-
fontWeight: 600,
|
|
2892
|
-
display: "flex",
|
|
2893
|
-
alignItems: "center",
|
|
2894
|
-
gap: "0.5rem"
|
|
2895
|
-
}, children: [
|
|
2896
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
2897
|
-
errorText
|
|
2898
|
-
] })
|
|
3330
|
+
errorText && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBanner, { margin: "0.75rem 0 0", children: errorText })
|
|
2899
3331
|
] });
|
|
2900
3332
|
}
|
|
2901
3333
|
function StripePaymentElementInner({
|
|
@@ -2923,17 +3355,17 @@ function StripePaymentElementInner({
|
|
|
2923
3355
|
expandedApmMethod
|
|
2924
3356
|
}) {
|
|
2925
3357
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2926
|
-
const [expandedMethod, setExpandedMethod] = (0,
|
|
2927
|
-
const [submittingMethod, setSubmittingMethod] = (0,
|
|
2928
|
-
const submittingRef = (0,
|
|
2929
|
-
(0,
|
|
3358
|
+
const [expandedMethod, setExpandedMethod] = (0, import_react10.useState)(null);
|
|
3359
|
+
const [submittingMethod, setSubmittingMethod] = (0, import_react10.useState)(null);
|
|
3360
|
+
const submittingRef = (0, import_react10.useRef)(false);
|
|
3361
|
+
(0, import_react10.useEffect)(() => {
|
|
2930
3362
|
if (paymentElementMethods.length > 0 && stripeInstance) {
|
|
2931
3363
|
onLoadStateChange?.("ready");
|
|
2932
3364
|
} else if (!stripeInstance) {
|
|
2933
3365
|
onLoadStateChange?.("loading");
|
|
2934
3366
|
}
|
|
2935
3367
|
}, [paymentElementMethods.length, stripeInstance, onLoadStateChange]);
|
|
2936
|
-
const handleAutoConfirm = (0,
|
|
3368
|
+
const handleAutoConfirm = (0, import_react10.useCallback)(async (method) => {
|
|
2937
3369
|
if (!stripeInstance) return;
|
|
2938
3370
|
if (submittingRef.current || isProcessing) return;
|
|
2939
3371
|
submittingRef.current = true;
|
|
@@ -2953,8 +3385,7 @@ function StripePaymentElementInner({
|
|
|
2953
3385
|
if (!effectiveSessionId || !effectiveEmail) {
|
|
2954
3386
|
throw new Error("Missing sessionId or email for payment.");
|
|
2955
3387
|
}
|
|
2956
|
-
const intentHeaders =
|
|
2957
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
3388
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2958
3389
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2959
3390
|
method: "POST",
|
|
2960
3391
|
headers: intentHeaders,
|
|
@@ -3020,9 +3451,8 @@ function StripePaymentElementInner({
|
|
|
3020
3451
|
onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
|
|
3021
3452
|
return;
|
|
3022
3453
|
}
|
|
3023
|
-
const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
|
|
3024
3454
|
const piStatus = paymentIntent?.status;
|
|
3025
|
-
if (!
|
|
3455
|
+
if (!isSuccessfulPaymentIntentStatus(piStatus)) {
|
|
3026
3456
|
if (typeof window !== "undefined") {
|
|
3027
3457
|
try {
|
|
3028
3458
|
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
@@ -3072,9 +3502,9 @@ function StripePaymentElementInner({
|
|
|
3072
3502
|
onErrorChange,
|
|
3073
3503
|
onDecline
|
|
3074
3504
|
]);
|
|
3075
|
-
const [localExpandedMethod, setLocalExpandedMethod] = (0,
|
|
3505
|
+
const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react10.useState)(null);
|
|
3076
3506
|
const activeExpandedMethod = onExpandApm ? expandedApmMethod ?? null : localExpandedMethod;
|
|
3077
|
-
const handleMethodClick = (0,
|
|
3507
|
+
const handleMethodClick = (0, import_react10.useCallback)((method) => {
|
|
3078
3508
|
if (submittingRef.current || isProcessing) return;
|
|
3079
3509
|
if (activeExpandedMethod && activeExpandedMethod !== method) return;
|
|
3080
3510
|
if ((0, import_shared5.needsStripeMethodExplicitConfirm)(method)) {
|
|
@@ -3087,14 +3517,14 @@ function StripePaymentElementInner({
|
|
|
3087
3517
|
void handleAutoConfirm(method);
|
|
3088
3518
|
}
|
|
3089
3519
|
}, [activeExpandedMethod, isProcessing, handleAutoConfirm, onExpandApm]);
|
|
3090
|
-
const localInlineElementsOptions = (0,
|
|
3520
|
+
const localInlineElementsOptions = (0, import_react10.useMemo)(() => {
|
|
3091
3521
|
if (!localExpandedMethod) return null;
|
|
3092
3522
|
return {
|
|
3093
3523
|
...paymentElementBaseOptions,
|
|
3094
3524
|
paymentMethodTypes: [localExpandedMethod]
|
|
3095
3525
|
};
|
|
3096
3526
|
}, [localExpandedMethod, paymentElementBaseOptions]);
|
|
3097
|
-
return /* @__PURE__ */ (0,
|
|
3527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3098
3528
|
"div",
|
|
3099
3529
|
{
|
|
3100
3530
|
"data-testid": "flopay-stripe-payment-element-region",
|
|
@@ -3103,8 +3533,8 @@ function StripePaymentElementInner({
|
|
|
3103
3533
|
const isExpanded = expandedApmMethod === method;
|
|
3104
3534
|
const isSubmittingThis = submittingMethod === method;
|
|
3105
3535
|
const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
|
|
3106
|
-
return /* @__PURE__ */ (0,
|
|
3107
|
-
/* @__PURE__ */ (0,
|
|
3536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react10.default.Fragment, { children: [
|
|
3537
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3108
3538
|
StripeMethodButton,
|
|
3109
3539
|
{
|
|
3110
3540
|
method,
|
|
@@ -3121,12 +3551,12 @@ function StripePaymentElementInner({
|
|
|
3121
3551
|
fontFamily: buttonAppearance?.fontFamily
|
|
3122
3552
|
}
|
|
3123
3553
|
),
|
|
3124
|
-
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0,
|
|
3554
|
+
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3125
3555
|
import_react_stripe_js.Elements,
|
|
3126
3556
|
{
|
|
3127
3557
|
stripe: stripeInstance,
|
|
3128
3558
|
options: localInlineElementsOptions,
|
|
3129
|
-
children: /* @__PURE__ */ (0,
|
|
3559
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3130
3560
|
StripeMethodInlineForm,
|
|
3131
3561
|
{
|
|
3132
3562
|
method,
|
|
@@ -3220,41 +3650,41 @@ function SplitCardFormInner({
|
|
|
3220
3650
|
const flopay = useFloPay();
|
|
3221
3651
|
const paypalFlopay = usePayPalFloPay();
|
|
3222
3652
|
const elements = useElements();
|
|
3223
|
-
const checkout = (0,
|
|
3653
|
+
const checkout = (0, import_react10.useContext)(CheckoutContext);
|
|
3224
3654
|
const contextBillingUrl = useBillingApiUrl();
|
|
3225
|
-
const [processing, setProcessing] = (0,
|
|
3226
|
-
const [error, setError] = (0,
|
|
3227
|
-
const [is3DSActive, setIs3DSActive] = (0,
|
|
3228
|
-
const [selectedCountry, setSelectedCountry] = (0,
|
|
3229
|
-
const [zipCode, setZipCode] = (0,
|
|
3230
|
-
const [addressLine1, setAddressLine1] = (0,
|
|
3231
|
-
const [addressLine2, setAddressLine2] = (0,
|
|
3232
|
-
const [city, setCity] = (0,
|
|
3233
|
-
const [stateValue, setStateValue] = (0,
|
|
3234
|
-
const [accountPatch, setAccountPatch] = (0,
|
|
3235
|
-
const zipCodeRef = (0,
|
|
3236
|
-
const selectedCountryRef = (0,
|
|
3237
|
-
const addressLine1Ref = (0,
|
|
3238
|
-
const addressLine2Ref = (0,
|
|
3239
|
-
const cityRef = (0,
|
|
3240
|
-
const stateRef = (0,
|
|
3241
|
-
const avsConfig = (0,
|
|
3655
|
+
const [processing, setProcessing] = (0, import_react10.useState)(false);
|
|
3656
|
+
const [error, setError] = (0, import_react10.useState)(null);
|
|
3657
|
+
const [is3DSActive, setIs3DSActive] = (0, import_react10.useState)(false);
|
|
3658
|
+
const [selectedCountry, setSelectedCountry] = (0, import_react10.useState)(countryProp ?? "US");
|
|
3659
|
+
const [zipCode, setZipCode] = (0, import_react10.useState)(zipProp ?? "");
|
|
3660
|
+
const [addressLine1, setAddressLine1] = (0, import_react10.useState)(addressLine1Prop ?? "");
|
|
3661
|
+
const [addressLine2, setAddressLine2] = (0, import_react10.useState)(addressLine2Prop ?? "");
|
|
3662
|
+
const [city, setCity] = (0, import_react10.useState)(cityProp ?? "");
|
|
3663
|
+
const [stateValue, setStateValue] = (0, import_react10.useState)(stateProp ?? "");
|
|
3664
|
+
const [accountPatch, setAccountPatch] = (0, import_react10.useState)({});
|
|
3665
|
+
const zipCodeRef = (0, import_react10.useRef)(zipProp ?? "");
|
|
3666
|
+
const selectedCountryRef = (0, import_react10.useRef)(countryProp ?? "US");
|
|
3667
|
+
const addressLine1Ref = (0, import_react10.useRef)(addressLine1Prop ?? "");
|
|
3668
|
+
const addressLine2Ref = (0, import_react10.useRef)(addressLine2Prop ?? "");
|
|
3669
|
+
const cityRef = (0, import_react10.useRef)(cityProp ?? "");
|
|
3670
|
+
const stateRef = (0, import_react10.useRef)(stateProp ?? "");
|
|
3671
|
+
const avsConfig = (0, import_react10.useMemo)(() => (0, import_shared5.resolveAVSConfig)(enableAVSProp), [enableAVSProp]);
|
|
3242
3672
|
const enableAVS = avsConfig !== null;
|
|
3243
3673
|
const vaultBlockReady = Boolean(session?.vault?.html);
|
|
3244
3674
|
const vaultGatewayAdvertised = Boolean(session?.gateways?.pcivault);
|
|
3245
3675
|
const vaultActive = Boolean(
|
|
3246
3676
|
showStripe && (vaultBlockReady || vaultGatewayAdvertised) && flopay && sessionId
|
|
3247
3677
|
);
|
|
3248
|
-
const cardCapture = (0,
|
|
3678
|
+
const cardCapture = (0, import_react10.useMemo)(() => {
|
|
3249
3679
|
if (!flopay || !vaultActive || !sessionId) return null;
|
|
3250
3680
|
return flopay.cardCapture({ sessionId });
|
|
3251
3681
|
}, [flopay, vaultActive, sessionId]);
|
|
3252
|
-
const postalCodeState = (0,
|
|
3682
|
+
const postalCodeState = (0, import_react10.useMemo)(() => {
|
|
3253
3683
|
const cc = selectedCountry;
|
|
3254
3684
|
const visible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) : false;
|
|
3255
3685
|
return computePostalCodeState(cc, zipCode, visible);
|
|
3256
3686
|
}, [avsConfig, selectedCountry, zipCode]);
|
|
3257
|
-
const { avsInvalid, invalidAvsFields } = (0,
|
|
3687
|
+
const { avsInvalid, invalidAvsFields } = (0, import_react10.useMemo)(() => {
|
|
3258
3688
|
const none = { line1: false, city: false, state: false, zip: false };
|
|
3259
3689
|
if (!vaultActive || !avsConfig) return { avsInvalid: false, invalidAvsFields: none };
|
|
3260
3690
|
const cc = selectedCountry;
|
|
@@ -3270,53 +3700,53 @@ function SplitCardFormInner({
|
|
|
3270
3700
|
const avsInvalid2 = invalidAvsFields2.line1 || invalidAvsFields2.city || invalidAvsFields2.state || invalidAvsFields2.zip;
|
|
3271
3701
|
return { avsInvalid: avsInvalid2, invalidAvsFields: invalidAvsFields2 };
|
|
3272
3702
|
}, [vaultActive, avsConfig, selectedCountry, addressLine1, city, stateValue, postalCodeState]);
|
|
3273
|
-
const [hasAttemptedSubmit, setHasAttemptedSubmit] = (0,
|
|
3274
|
-
const [zipTouched, setZipTouched] = (0,
|
|
3275
|
-
const [vaultMount, setVaultMount] = (0,
|
|
3703
|
+
const [hasAttemptedSubmit, setHasAttemptedSubmit] = (0, import_react10.useState)(false);
|
|
3704
|
+
const [zipTouched, setZipTouched] = (0, import_react10.useState)(false);
|
|
3705
|
+
const [vaultMount, setVaultMount] = (0, import_react10.useState)(
|
|
3276
3706
|
() => toVaultMount(session?.vault)
|
|
3277
3707
|
);
|
|
3278
|
-
const [viewState, setViewState] = (0,
|
|
3279
|
-
const [expandedApmMethod, setExpandedApmMethod] = (0,
|
|
3708
|
+
const [viewState, setViewState] = (0, import_react10.useState)(initialCardOpen ? "card" : "buttons");
|
|
3709
|
+
const [expandedApmMethod, setExpandedApmMethod] = (0, import_react10.useState)(null);
|
|
3280
3710
|
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
3281
3711
|
const TRANSITION_MS = 280;
|
|
3282
|
-
const expandToCard = (0,
|
|
3712
|
+
const expandToCard = (0, import_react10.useCallback)(() => {
|
|
3283
3713
|
setViewState("expanding");
|
|
3284
3714
|
setTimeout(() => setViewState("card"), TRANSITION_MS);
|
|
3285
3715
|
}, []);
|
|
3286
|
-
const collapseToButtons = (0,
|
|
3716
|
+
const collapseToButtons = (0, import_react10.useCallback)(() => {
|
|
3287
3717
|
setViewState("collapsing");
|
|
3288
3718
|
setTimeout(() => setViewState("buttons"), TRANSITION_MS);
|
|
3289
3719
|
}, []);
|
|
3290
|
-
const expandToApm = (0,
|
|
3720
|
+
const expandToApm = (0, import_react10.useCallback)((method) => {
|
|
3291
3721
|
setExpandedApmMethod(method);
|
|
3292
3722
|
setViewState("apm-expanding");
|
|
3293
3723
|
setTimeout(() => setViewState("apm-form"), TRANSITION_MS);
|
|
3294
3724
|
}, []);
|
|
3295
|
-
const collapseFromApm = (0,
|
|
3725
|
+
const collapseFromApm = (0, import_react10.useCallback)(() => {
|
|
3296
3726
|
setViewState("apm-collapsing");
|
|
3297
3727
|
setTimeout(() => {
|
|
3298
3728
|
setViewState("buttons");
|
|
3299
3729
|
setExpandedApmMethod(null);
|
|
3300
3730
|
}, TRANSITION_MS);
|
|
3301
3731
|
}, []);
|
|
3302
|
-
(0,
|
|
3732
|
+
(0, import_react10.useEffect)(() => {
|
|
3303
3733
|
if (layout === "buttons" && initialCardOpen) {
|
|
3304
3734
|
setViewState("card");
|
|
3305
3735
|
}
|
|
3306
3736
|
}, [layout, initialCardOpen]);
|
|
3307
|
-
const [fullName, setFullName] = (0,
|
|
3308
|
-
const [formReady, setFormReady] = (0,
|
|
3309
|
-
const [overlayStatus, setOverlayStatus] = (0,
|
|
3310
|
-
const processingRef = (0,
|
|
3311
|
-
const [paypalDirectRetry, setPaypalDirectRetry] = (0,
|
|
3312
|
-
const paypalDirectRetryRef = (0,
|
|
3313
|
-
(0,
|
|
3737
|
+
const [fullName, setFullName] = (0, import_react10.useState)("");
|
|
3738
|
+
const [formReady, setFormReady] = (0, import_react10.useState)(false);
|
|
3739
|
+
const [overlayStatus, setOverlayStatus] = (0, import_react10.useState)(null);
|
|
3740
|
+
const processingRef = (0, import_react10.useRef)(false);
|
|
3741
|
+
const [paypalDirectRetry, setPaypalDirectRetry] = (0, import_react10.useState)(null);
|
|
3742
|
+
const paypalDirectRetryRef = (0, import_react10.useRef)(paypalDirectRetry);
|
|
3743
|
+
(0, import_react10.useEffect)(() => {
|
|
3314
3744
|
paypalDirectRetryRef.current = paypalDirectRetry;
|
|
3315
3745
|
}, [paypalDirectRetry]);
|
|
3316
3746
|
const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
|
|
3317
3747
|
const displayError = externalError ?? error;
|
|
3318
|
-
const themeBundle = (0,
|
|
3319
|
-
const bStyles = (0,
|
|
3748
|
+
const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
|
|
3749
|
+
const bStyles = (0, import_react10.useMemo)(() => {
|
|
3320
3750
|
const base = themeBundle?.buttonsLayout ?? (0, import_shared5.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
3321
3751
|
if (!buttonsStylesOverride) return base;
|
|
3322
3752
|
return {
|
|
@@ -3331,7 +3761,7 @@ function SplitCardFormInner({
|
|
|
3331
3761
|
};
|
|
3332
3762
|
}, [themeBundle, buttonsTheme, buttonsStylesOverride]);
|
|
3333
3763
|
const appearance = appearanceOverride ?? themeBundle?.appearance;
|
|
3334
|
-
const vaultThemeColors = (0,
|
|
3764
|
+
const vaultThemeColors = (0, import_react10.useMemo)(() => {
|
|
3335
3765
|
const vars = appearance?.variables;
|
|
3336
3766
|
const asString = (value) => typeof value === "string" && value ? value : void 0;
|
|
3337
3767
|
const submitButtonStyle = bStyles.submitButton;
|
|
@@ -3360,7 +3790,7 @@ function SplitCardFormInner({
|
|
|
3360
3790
|
const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
|
|
3361
3791
|
const isSelfContained = !onTokenizedBody;
|
|
3362
3792
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
3363
|
-
const resolvedAccount = (0,
|
|
3793
|
+
const resolvedAccount = (0, import_react10.useMemo)(() => mergeAccountPatch({
|
|
3364
3794
|
userId,
|
|
3365
3795
|
email,
|
|
3366
3796
|
firstName,
|
|
@@ -3368,17 +3798,17 @@ function SplitCardFormInner({
|
|
|
3368
3798
|
country: countryProp,
|
|
3369
3799
|
zip: zipProp
|
|
3370
3800
|
}, accountPatch), [userId, email, firstName, lastName, countryProp, zipProp, accountPatch]);
|
|
3371
|
-
const stripeInstance = (0,
|
|
3801
|
+
const stripeInstance = (0, import_react10.useMemo)(() => {
|
|
3372
3802
|
if (!flopay) return null;
|
|
3373
3803
|
return flopay.getRawProvider();
|
|
3374
3804
|
}, [flopay]);
|
|
3375
|
-
const paypalStripeInstance = (0,
|
|
3805
|
+
const paypalStripeInstance = (0, import_react10.useMemo)(() => {
|
|
3376
3806
|
if (!paypalFlopay) return null;
|
|
3377
3807
|
return paypalFlopay.getRawProvider();
|
|
3378
3808
|
}, [paypalFlopay]);
|
|
3379
3809
|
const amountInCents = totalAmount || 100;
|
|
3380
3810
|
const stripeAppearanceProp = appearance ? { appearance } : null;
|
|
3381
|
-
const paymentElementAppearance = (0,
|
|
3811
|
+
const paymentElementAppearance = (0, import_react10.useMemo)(() => {
|
|
3382
3812
|
const base = appearance ?? {};
|
|
3383
3813
|
const baseRules = base.rules ?? {};
|
|
3384
3814
|
return {
|
|
@@ -3398,7 +3828,7 @@ function SplitCardFormInner({
|
|
|
3398
3828
|
}
|
|
3399
3829
|
};
|
|
3400
3830
|
}, [appearance]);
|
|
3401
|
-
const walletOptions = (0,
|
|
3831
|
+
const walletOptions = (0, import_react10.useMemo)(() => {
|
|
3402
3832
|
const modeOptions = resolveWalletElementsMode(totalAmount);
|
|
3403
3833
|
return {
|
|
3404
3834
|
...modeOptions,
|
|
@@ -3409,7 +3839,7 @@ function SplitCardFormInner({
|
|
|
3409
3839
|
...stripeAppearanceProp
|
|
3410
3840
|
};
|
|
3411
3841
|
}, [totalAmount, currency, stripeAppearanceProp]);
|
|
3412
|
-
const paypalOptions = (0,
|
|
3842
|
+
const paypalOptions = (0, import_react10.useMemo)(() => ({
|
|
3413
3843
|
mode: "payment",
|
|
3414
3844
|
amount: amountInCents,
|
|
3415
3845
|
currency: currency.toLowerCase(),
|
|
@@ -3417,29 +3847,29 @@ function SplitCardFormInner({
|
|
|
3417
3847
|
setupFutureUsage: "off_session",
|
|
3418
3848
|
...stripeAppearanceProp
|
|
3419
3849
|
}), [amountInCents, currency, stripeAppearanceProp]);
|
|
3420
|
-
const updateError = (0,
|
|
3850
|
+
const updateError = (0, import_react10.useCallback)(
|
|
3421
3851
|
(err) => {
|
|
3422
3852
|
setError(err);
|
|
3423
3853
|
onErrorChange?.(err);
|
|
3424
3854
|
},
|
|
3425
3855
|
[onErrorChange]
|
|
3426
3856
|
);
|
|
3427
|
-
(0,
|
|
3857
|
+
(0, import_react10.useEffect)(() => {
|
|
3428
3858
|
if (!vaultActive || !cardCapture) return;
|
|
3429
3859
|
cardCapture.setCardFieldOrder?.(cardFieldOrder ?? null, avsConfig == null);
|
|
3430
3860
|
}, [vaultActive, cardCapture, cardFieldOrder, avsConfig]);
|
|
3431
|
-
(0,
|
|
3861
|
+
(0, import_react10.useEffect)(() => {
|
|
3432
3862
|
if (viewState === "expanding" || viewState === "collapsing" || viewState === "apm-expanding" || viewState === "apm-collapsing") {
|
|
3433
3863
|
updateError(null);
|
|
3434
3864
|
}
|
|
3435
3865
|
}, [viewState, updateError]);
|
|
3436
|
-
const emitDecline = (0,
|
|
3866
|
+
const emitDecline = (0, import_react10.useCallback)(
|
|
3437
3867
|
(method, input, overrides) => {
|
|
3438
3868
|
onDecline?.(buildDeclineEvent(method, input, overrides));
|
|
3439
3869
|
},
|
|
3440
3870
|
[onDecline]
|
|
3441
3871
|
);
|
|
3442
|
-
const recoverExternalMethodTechnicalFailure = (0,
|
|
3872
|
+
const recoverExternalMethodTechnicalFailure = (0, import_react10.useCallback)(
|
|
3443
3873
|
(method, err, options) => {
|
|
3444
3874
|
const popupBlocked = options?.popupBlocked ?? isPopupBlockedError(err);
|
|
3445
3875
|
const message = buildExternalMethodRecoveryMessage(method, popupBlocked);
|
|
@@ -3463,7 +3893,7 @@ function SplitCardFormInner({
|
|
|
3463
3893
|
},
|
|
3464
3894
|
[layout, onError, updateError]
|
|
3465
3895
|
);
|
|
3466
|
-
(0,
|
|
3896
|
+
(0, import_react10.useEffect)(() => {
|
|
3467
3897
|
if (!vaultActive || !sessionId) {
|
|
3468
3898
|
setVaultMount(null);
|
|
3469
3899
|
return;
|
|
@@ -3501,7 +3931,7 @@ function SplitCardFormInner({
|
|
|
3501
3931
|
nonce,
|
|
3502
3932
|
updateError
|
|
3503
3933
|
]);
|
|
3504
|
-
const vaultOutcomeRef = (0,
|
|
3934
|
+
const vaultOutcomeRef = (0, import_react10.useRef)({
|
|
3505
3935
|
onComplete,
|
|
3506
3936
|
onError,
|
|
3507
3937
|
updateError,
|
|
@@ -3527,8 +3957,8 @@ function SplitCardFormInner({
|
|
|
3527
3957
|
nonce,
|
|
3528
3958
|
baseUrl
|
|
3529
3959
|
};
|
|
3530
|
-
const vaultCompletedRef = (0,
|
|
3531
|
-
const buildVaultAccountSnapshot = (0,
|
|
3960
|
+
const vaultCompletedRef = (0, import_react10.useRef)(false);
|
|
3961
|
+
const buildVaultAccountSnapshot = (0, import_react10.useCallback)(() => {
|
|
3532
3962
|
const { resolvedAccount: resolvedAccount2, avsConfig: avsConfig2, fullName: fullName2, avsCheckProp: avsCheckProp2 } = vaultOutcomeRef.current;
|
|
3533
3963
|
const cc = selectedCountryRef.current || resolvedAccount2.country || "US";
|
|
3534
3964
|
const stateVisible = avsConfig2 ? (0, import_shared5.isAVSFieldVisible)(avsConfig2.state, cc) : false;
|
|
@@ -3564,11 +3994,11 @@ function SplitCardFormInner({
|
|
|
3564
3994
|
} : {}
|
|
3565
3995
|
};
|
|
3566
3996
|
}, []);
|
|
3567
|
-
(0,
|
|
3997
|
+
(0, import_react10.useEffect)(() => {
|
|
3568
3998
|
if (!vaultActive || !cardCapture) return;
|
|
3569
3999
|
cardCapture.setSubmitGate?.(avsInvalid);
|
|
3570
4000
|
}, [vaultActive, cardCapture, avsInvalid]);
|
|
3571
|
-
(0,
|
|
4001
|
+
(0, import_react10.useEffect)(() => {
|
|
3572
4002
|
if (!vaultActive || !cardCapture) return;
|
|
3573
4003
|
vaultCompletedRef.current = false;
|
|
3574
4004
|
let cancelled = false;
|
|
@@ -3629,18 +4059,18 @@ function SplitCardFormInner({
|
|
|
3629
4059
|
const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
|
|
3630
4060
|
const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
|
|
3631
4061
|
const paypalEnabled = hasEnabledMethodsPayload && enabledPaymentMethods.includes("paypal");
|
|
3632
|
-
const { expressMethods, paymentElementMethods } = (0,
|
|
4062
|
+
const { expressMethods, paymentElementMethods } = (0, import_react10.useMemo)(
|
|
3633
4063
|
() => (0, import_shared5.partitionStripeMethods)(enabledPaymentMethods, {
|
|
3634
4064
|
excludePaypal: directPaypalConfigured
|
|
3635
4065
|
}),
|
|
3636
4066
|
[enabledPaymentMethods, directPaypalConfigured]
|
|
3637
4067
|
);
|
|
3638
4068
|
const paypalRenderedSeparately = directPaypalConfigured || !!paypalFlopay;
|
|
3639
|
-
const expressMethodsForWalletRow = (0,
|
|
4069
|
+
const expressMethodsForWalletRow = (0, import_react10.useMemo)(
|
|
3640
4070
|
() => paypalRenderedSeparately ? expressMethods.filter((m) => m !== "paypal") : expressMethods,
|
|
3641
4071
|
[expressMethods, paypalRenderedSeparately]
|
|
3642
4072
|
);
|
|
3643
|
-
const legacyExpressMethods = (0,
|
|
4073
|
+
const legacyExpressMethods = (0, import_react10.useMemo)(() => {
|
|
3644
4074
|
const out = [];
|
|
3645
4075
|
if (showApplePay) out.push("apple_pay");
|
|
3646
4076
|
if (showGooglePay) out.push("google_pay");
|
|
@@ -3649,7 +4079,7 @@ function SplitCardFormInner({
|
|
|
3649
4079
|
const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
|
|
3650
4080
|
const showWallets = showStripe && walletExpressMethods.length > 0;
|
|
3651
4081
|
const apmCountry = enableAVS ? selectedCountry : countryProp;
|
|
3652
|
-
const paymentElementMethodsForCurrency = (0,
|
|
4082
|
+
const paymentElementMethodsForCurrency = (0, import_react10.useMemo)(() => {
|
|
3653
4083
|
const target = apmCountry?.trim().toUpperCase();
|
|
3654
4084
|
if (!target) return paymentElementMethods;
|
|
3655
4085
|
if (!enabledPaymentMethodCountries) {
|
|
@@ -3660,19 +4090,19 @@ function SplitCardFormInner({
|
|
|
3660
4090
|
return !allowed || allowed.length === 0 || allowed.includes(target);
|
|
3661
4091
|
});
|
|
3662
4092
|
}, [paymentElementMethods, apmCountry, enabledPaymentMethodCountries]);
|
|
3663
|
-
const paymentElementBaseOptions = (0,
|
|
4093
|
+
const paymentElementBaseOptions = (0, import_react10.useMemo)(() => ({
|
|
3664
4094
|
mode: "payment",
|
|
3665
4095
|
amount: amountInCents,
|
|
3666
4096
|
currency: currency.toLowerCase(),
|
|
3667
4097
|
paymentMethodCreation: "manual",
|
|
3668
4098
|
appearance: paymentElementAppearance
|
|
3669
4099
|
}), [amountInCents, currency, paymentElementAppearance]);
|
|
3670
|
-
const [paypalLoadState, setPaypalLoadState] = (0,
|
|
3671
|
-
const [walletLoadState, setWalletLoadState] = (0,
|
|
3672
|
-
const [paymentElementLoadState, setPaymentElementLoadState] = (0,
|
|
3673
|
-
const [directPaypalReady, setDirectPaypalReady] = (0,
|
|
3674
|
-
const [inAppBrowserDetected, setInAppBrowserDetected] = (0,
|
|
3675
|
-
(0,
|
|
4100
|
+
const [paypalLoadState, setPaypalLoadState] = (0, import_react10.useState)("loading");
|
|
4101
|
+
const [walletLoadState, setWalletLoadState] = (0, import_react10.useState)("loading");
|
|
4102
|
+
const [paymentElementLoadState, setPaymentElementLoadState] = (0, import_react10.useState)("loading");
|
|
4103
|
+
const [directPaypalReady, setDirectPaypalReady] = (0, import_react10.useState)(false);
|
|
4104
|
+
const [inAppBrowserDetected, setInAppBrowserDetected] = (0, import_react10.useState)();
|
|
4105
|
+
(0, import_react10.useEffect)(() => {
|
|
3676
4106
|
setInAppBrowserDetected(isInAppBrowser());
|
|
3677
4107
|
}, []);
|
|
3678
4108
|
const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
|
|
@@ -3684,8 +4114,8 @@ function SplitCardFormInner({
|
|
|
3684
4114
|
const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
|
|
3685
4115
|
const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
|
|
3686
4116
|
const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
|
|
3687
|
-
const validationFiredRef = (0,
|
|
3688
|
-
(0,
|
|
4117
|
+
const validationFiredRef = (0, import_react10.useRef)(false);
|
|
4118
|
+
(0, import_react10.useEffect)(() => {
|
|
3689
4119
|
if (validationFiredRef.current) return;
|
|
3690
4120
|
if (!showStripe && !showPayPal) {
|
|
3691
4121
|
validationFiredRef.current = true;
|
|
@@ -3705,8 +4135,8 @@ function SplitCardFormInner({
|
|
|
3705
4135
|
updateError(err.message);
|
|
3706
4136
|
}
|
|
3707
4137
|
}, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
|
|
3708
|
-
const deprecationLoggedRef = (0,
|
|
3709
|
-
(0,
|
|
4138
|
+
const deprecationLoggedRef = (0, import_react10.useRef)(false);
|
|
4139
|
+
(0, import_react10.useEffect)(() => {
|
|
3710
4140
|
if (deprecationLoggedRef.current) return;
|
|
3711
4141
|
if (!hasEnabledMethods) return;
|
|
3712
4142
|
const stale = [];
|
|
@@ -3718,14 +4148,14 @@ function SplitCardFormInner({
|
|
|
3718
4148
|
`[FloPay] ${stale.join(" / ")} ${stale.length === 1 ? "is" : "are"} deprecated: the Apple Pay / Google Pay surface is now driven by \`gateways.stripe.enabledPaymentMethods\` on the session response. Remove the legacy prop(s) to silence this warning.`
|
|
3719
4149
|
);
|
|
3720
4150
|
}, [hasEnabledMethods, showApplePay, showGooglePay]);
|
|
3721
|
-
const handleNameChange = (0,
|
|
4151
|
+
const handleNameChange = (0, import_react10.useCallback)((value) => {
|
|
3722
4152
|
setFullName(value);
|
|
3723
4153
|
onFullNameChange?.(value);
|
|
3724
4154
|
const parts = value.trim().split(/\s+/);
|
|
3725
4155
|
onFirstNameChange?.(parts[0] ?? "");
|
|
3726
4156
|
onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
|
|
3727
4157
|
}, [onFullNameChange, onFirstNameChange, onLastNameChange]);
|
|
3728
|
-
const applyInlineSessionPatch = (0,
|
|
4158
|
+
const applyInlineSessionPatch = (0, import_react10.useCallback)(
|
|
3729
4159
|
(patch, method) => {
|
|
3730
4160
|
if (!checkout.applyInlineSessionPatch) {
|
|
3731
4161
|
return Promise.resolve({ error: null, sessionId, nonce });
|
|
@@ -3747,7 +4177,7 @@ function SplitCardFormInner({
|
|
|
3747
4177
|
},
|
|
3748
4178
|
[checkout.applyInlineSessionPatch, nonce, onError, sessionId, updateError]
|
|
3749
4179
|
);
|
|
3750
|
-
const runBeforeButtonClick = (0,
|
|
4180
|
+
const runBeforeButtonClick = (0, import_react10.useCallback)(async (method) => {
|
|
3751
4181
|
if (!onBeforeButtonClick) return { proceed: true };
|
|
3752
4182
|
try {
|
|
3753
4183
|
const result = await onBeforeButtonClick({
|
|
@@ -3784,7 +4214,7 @@ function SplitCardFormInner({
|
|
|
3784
4214
|
return { proceed: false };
|
|
3785
4215
|
}
|
|
3786
4216
|
}, [applyInlineSessionPatch, checkout.inlineSessionDraft, onBeforeButtonClick, onError, sessionId, updateError]);
|
|
3787
|
-
const processPaymentInternal = (0,
|
|
4217
|
+
const processPaymentInternal = (0, import_react10.useCallback)(
|
|
3788
4218
|
async (tokenizedBody, overrides) => {
|
|
3789
4219
|
if (processingRef.current) return;
|
|
3790
4220
|
processingRef.current = true;
|
|
@@ -3995,7 +4425,7 @@ function SplitCardFormInner({
|
|
|
3995
4425
|
},
|
|
3996
4426
|
[baseUrl, sessionId, nonce, resolvedAccount, fullName, chv, flopay, paypalFlopay, onComplete, onError, updateError, emitDecline]
|
|
3997
4427
|
);
|
|
3998
|
-
const dispatchTokenizedBody = (0,
|
|
4428
|
+
const dispatchTokenizedBody = (0, import_react10.useCallback)(
|
|
3999
4429
|
(tokenizedBody, overrides) => {
|
|
4000
4430
|
if (onTokenizedBody) {
|
|
4001
4431
|
onTokenizedBody(tokenizedBody);
|
|
@@ -4005,7 +4435,7 @@ function SplitCardFormInner({
|
|
|
4005
4435
|
},
|
|
4006
4436
|
[onTokenizedBody, processPaymentInternal]
|
|
4007
4437
|
);
|
|
4008
|
-
(0,
|
|
4438
|
+
(0, import_react10.useImperativeHandle)(innerRef, () => ({
|
|
4009
4439
|
async handleNextAction(secret) {
|
|
4010
4440
|
if (!flopay) return;
|
|
4011
4441
|
setIs3DSActive(true);
|
|
@@ -4032,8 +4462,8 @@ function SplitCardFormInner({
|
|
|
4032
4462
|
}
|
|
4033
4463
|
}
|
|
4034
4464
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
4035
|
-
const stripeResumeAttemptedRef = (0,
|
|
4036
|
-
(0,
|
|
4465
|
+
const stripeResumeAttemptedRef = (0, import_react10.useRef)(false);
|
|
4466
|
+
(0, import_react10.useEffect)(() => {
|
|
4037
4467
|
if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
|
|
4038
4468
|
const params = new URLSearchParams(window.location.search);
|
|
4039
4469
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -4094,7 +4524,7 @@ function SplitCardFormInner({
|
|
|
4094
4524
|
return;
|
|
4095
4525
|
}
|
|
4096
4526
|
const piStatus = paymentIntent?.status;
|
|
4097
|
-
const successful = piStatus
|
|
4527
|
+
const successful = isSuccessfulPaymentIntentStatus(piStatus);
|
|
4098
4528
|
if (!paymentIntent || !successful) {
|
|
4099
4529
|
const message = piStatus === "canceled" ? "Payment was canceled." : "Payment was not completed. Please try again.";
|
|
4100
4530
|
updateError(message);
|
|
@@ -4111,7 +4541,7 @@ function SplitCardFormInner({
|
|
|
4111
4541
|
}, persistedOverrides);
|
|
4112
4542
|
})();
|
|
4113
4543
|
}, [sessionId, dispatchTokenizedBody, flopay, updateError, emitDecline]);
|
|
4114
|
-
const handleSubmit = (0,
|
|
4544
|
+
const handleSubmit = (0, import_react10.useCallback)(
|
|
4115
4545
|
async (e) => {
|
|
4116
4546
|
e.preventDefault();
|
|
4117
4547
|
if (!flopay || !elements || isSubmitting || processingRef.current) return;
|
|
@@ -4194,8 +4624,7 @@ function SplitCardFormInner({
|
|
|
4194
4624
|
updateError(pmResult.error?.message ?? "Failed to create payment method.");
|
|
4195
4625
|
return;
|
|
4196
4626
|
}
|
|
4197
|
-
const intentHeaders =
|
|
4198
|
-
if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
|
|
4627
|
+
const intentHeaders = intentRequestHeaders(nonce);
|
|
4199
4628
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
4200
4629
|
method: "POST",
|
|
4201
4630
|
headers: intentHeaders,
|
|
@@ -4271,7 +4700,7 @@ function SplitCardFormInner({
|
|
|
4271
4700
|
);
|
|
4272
4701
|
const isReady = flopay !== null && (vaultActive || elements !== null);
|
|
4273
4702
|
if (!isReady) {
|
|
4274
|
-
return /* @__PURE__ */ (0,
|
|
4703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
|
|
4275
4704
|
}
|
|
4276
4705
|
const isButtons = layout === "buttons";
|
|
4277
4706
|
const appearanceVars = appearance?.variables;
|
|
@@ -4330,7 +4759,7 @@ function SplitCardFormInner({
|
|
|
4330
4759
|
const containerOverrides = bStyles.cardFormContainer ?? {};
|
|
4331
4760
|
const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
|
|
4332
4761
|
const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
|
|
4333
|
-
const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ (0,
|
|
4762
|
+
const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4334
4763
|
VaultCardFields,
|
|
4335
4764
|
{
|
|
4336
4765
|
capture: cardCapture,
|
|
@@ -4368,7 +4797,7 @@ function SplitCardFormInner({
|
|
|
4368
4797
|
if (message) setOverlayStatus(null);
|
|
4369
4798
|
}
|
|
4370
4799
|
}
|
|
4371
|
-
) : /* @__PURE__ */ (0,
|
|
4800
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4372
4801
|
"div",
|
|
4373
4802
|
{
|
|
4374
4803
|
"data-testid": "flopay-vault-loading",
|
|
@@ -4383,7 +4812,7 @@ function SplitCardFormInner({
|
|
|
4383
4812
|
children: "Loading secure card form\u2026"
|
|
4384
4813
|
}
|
|
4385
4814
|
);
|
|
4386
|
-
const cardFormBlock = /* @__PURE__ */ (0,
|
|
4815
|
+
const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
4387
4816
|
backgroundColor: cardBg,
|
|
4388
4817
|
borderRadius: containerRadius,
|
|
4389
4818
|
...containerOverrides,
|
|
@@ -4396,7 +4825,7 @@ function SplitCardFormInner({
|
|
|
4396
4825
|
display: "flex",
|
|
4397
4826
|
flexDirection: "column"
|
|
4398
4827
|
}, children: [
|
|
4399
|
-
/* @__PURE__ */ (0,
|
|
4828
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
|
|
4400
4829
|
.flopay-shared-input::placeholder {
|
|
4401
4830
|
color: var(--flopay-input-placeholder-color);
|
|
4402
4831
|
opacity: 1;
|
|
@@ -4405,14 +4834,14 @@ function SplitCardFormInner({
|
|
|
4405
4834
|
font-weight: var(--flopay-input-font-weight);
|
|
4406
4835
|
}
|
|
4407
4836
|
` }),
|
|
4408
|
-
isButtons && showCardForm && /* @__PURE__ */ (0,
|
|
4837
|
+
isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
4409
4838
|
display: "flex",
|
|
4410
4839
|
alignItems: "center",
|
|
4411
4840
|
padding: "0.75rem 0 0.625rem",
|
|
4412
4841
|
// Keep the header on top when AVS is ordered above the card on vault.
|
|
4413
4842
|
order: vaultActive ? -2 : 0
|
|
4414
4843
|
}, children: [
|
|
4415
|
-
/* @__PURE__ */ (0,
|
|
4844
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
4416
4845
|
"button",
|
|
4417
4846
|
{
|
|
4418
4847
|
type: "button",
|
|
@@ -4434,7 +4863,7 @@ function SplitCardFormInner({
|
|
|
4434
4863
|
},
|
|
4435
4864
|
"aria-label": "Back to payment methods",
|
|
4436
4865
|
children: [
|
|
4437
|
-
/* @__PURE__ */ (0,
|
|
4866
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
4438
4867
|
display: "inline-flex",
|
|
4439
4868
|
alignItems: "center",
|
|
4440
4869
|
justifyContent: "center",
|
|
@@ -4444,12 +4873,12 @@ function SplitCardFormInner({
|
|
|
4444
4873
|
backgroundColor: "#f3f4f6",
|
|
4445
4874
|
transition: "background-color 0.15s",
|
|
4446
4875
|
...bStyles.backButtonIcon
|
|
4447
|
-
}, children: /* @__PURE__ */ (0,
|
|
4448
|
-
/* @__PURE__ */ (0,
|
|
4876
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
4877
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
4449
4878
|
]
|
|
4450
4879
|
}
|
|
4451
4880
|
),
|
|
4452
|
-
hideTitle ? /* @__PURE__ */ (0,
|
|
4881
|
+
hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4453
4882
|
flex: 1,
|
|
4454
4883
|
textAlign: "center",
|
|
4455
4884
|
fontWeight: 600,
|
|
@@ -4457,9 +4886,9 @@ function SplitCardFormInner({
|
|
|
4457
4886
|
color: "#262833",
|
|
4458
4887
|
paddingRight: 80,
|
|
4459
4888
|
...bStyles.title
|
|
4460
|
-
}, children: /* @__PURE__ */ (0,
|
|
4889
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) })
|
|
4461
4890
|
] }),
|
|
4462
|
-
!isButtons && !hideTitle && /* @__PURE__ */ (0,
|
|
4891
|
+
!isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4463
4892
|
textAlign: "center",
|
|
4464
4893
|
fontWeight: 600,
|
|
4465
4894
|
fontSize: "1.1rem",
|
|
@@ -4469,17 +4898,17 @@ function SplitCardFormInner({
|
|
|
4469
4898
|
// (-2) and AVS block (-1) are ordered below it but above the card form.
|
|
4470
4899
|
order: vaultActive ? -3 : 0,
|
|
4471
4900
|
...bStyles.title
|
|
4472
|
-
}, children: /* @__PURE__ */ (0,
|
|
4473
|
-
!vaultActive && /* @__PURE__ */ (0,
|
|
4474
|
-
/* @__PURE__ */ (0,
|
|
4901
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
|
|
4902
|
+
!vaultActive && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
4903
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4475
4904
|
backgroundColor: cardInputBg,
|
|
4476
4905
|
border: `1px solid ${resolvedBorder}`,
|
|
4477
4906
|
borderTopLeftRadius: resolvedBorderRadius,
|
|
4478
4907
|
borderTopRightRadius: resolvedBorderRadius,
|
|
4479
4908
|
padding: "10px"
|
|
4480
|
-
}, children: /* @__PURE__ */ (0,
|
|
4481
|
-
/* @__PURE__ */ (0,
|
|
4482
|
-
/* @__PURE__ */ (0,
|
|
4909
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
4910
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex" }, children: [
|
|
4911
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4483
4912
|
flex: 1,
|
|
4484
4913
|
backgroundColor: cardInputBg,
|
|
4485
4914
|
// Longhand only — mixing `border` shorthand with per-side
|
|
@@ -4491,8 +4920,8 @@ function SplitCardFormInner({
|
|
|
4491
4920
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
4492
4921
|
borderBottomLeftRadius: resolvedBorderRadius,
|
|
4493
4922
|
padding: "10px"
|
|
4494
|
-
}, children: /* @__PURE__ */ (0,
|
|
4495
|
-
/* @__PURE__ */ (0,
|
|
4923
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
4924
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4496
4925
|
flex: 1,
|
|
4497
4926
|
backgroundColor: cardInputBg,
|
|
4498
4927
|
borderTop: "none",
|
|
@@ -4501,16 +4930,16 @@ function SplitCardFormInner({
|
|
|
4501
4930
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
4502
4931
|
borderBottomRightRadius: resolvedBorderRadius,
|
|
4503
4932
|
padding: "10px"
|
|
4504
|
-
}, children: /* @__PURE__ */ (0,
|
|
4933
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardCvcElement, { options: stripeElementStyle }) })
|
|
4505
4934
|
] })
|
|
4506
4935
|
] }),
|
|
4507
|
-
!vaultActive && /* @__PURE__ */ (0,
|
|
4936
|
+
!vaultActive && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4508
4937
|
backgroundColor: cardInputBg,
|
|
4509
4938
|
border: `1px solid ${resolvedBorder}`,
|
|
4510
4939
|
borderRadius: resolvedBorderRadius,
|
|
4511
4940
|
marginTop: "0.5rem",
|
|
4512
4941
|
padding: "10px"
|
|
4513
|
-
}, children: /* @__PURE__ */ (0,
|
|
4942
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4514
4943
|
"input",
|
|
4515
4944
|
{
|
|
4516
4945
|
className: "flopay-shared-input",
|
|
@@ -4532,7 +4961,7 @@ function SplitCardFormInner({
|
|
|
4532
4961
|
}
|
|
4533
4962
|
}
|
|
4534
4963
|
) }),
|
|
4535
|
-
avsConfig && /* @__PURE__ */ (0,
|
|
4964
|
+
avsConfig && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
|
|
4536
4965
|
const cc = selectedCountry;
|
|
4537
4966
|
const inputWrapStyle = (invalid = false) => ({
|
|
4538
4967
|
backgroundColor: cardInputBg,
|
|
@@ -4549,8 +4978,8 @@ function SplitCardFormInner({
|
|
|
4549
4978
|
...sharedInputTypography
|
|
4550
4979
|
});
|
|
4551
4980
|
const stateOpts = (0, import_shared5.getStateOptions)(cc);
|
|
4552
|
-
return /* @__PURE__ */ (0,
|
|
4553
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) && /* @__PURE__ */ (0,
|
|
4981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
4982
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: inputWrapStyle(invalidAvsFields.line1), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4554
4983
|
"input",
|
|
4555
4984
|
{
|
|
4556
4985
|
className: "flopay-shared-input",
|
|
@@ -4569,7 +4998,7 @@ function SplitCardFormInner({
|
|
|
4569
4998
|
style: inputFieldStyle()
|
|
4570
4999
|
}
|
|
4571
5000
|
) }),
|
|
4572
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) && /* @__PURE__ */ (0,
|
|
5001
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: inputWrapStyle(), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4573
5002
|
"input",
|
|
4574
5003
|
{
|
|
4575
5004
|
className: "flopay-shared-input",
|
|
@@ -4587,12 +5016,12 @@ function SplitCardFormInner({
|
|
|
4587
5016
|
style: inputFieldStyle()
|
|
4588
5017
|
}
|
|
4589
5018
|
) }),
|
|
4590
|
-
((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0,
|
|
5019
|
+
((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
4591
5020
|
display: "flex",
|
|
4592
5021
|
gap: "0",
|
|
4593
5022
|
marginTop: "0.5rem"
|
|
4594
5023
|
}, children: [
|
|
4595
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0,
|
|
5024
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4596
5025
|
flex: 1,
|
|
4597
5026
|
backgroundColor: cardInputBg,
|
|
4598
5027
|
borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
@@ -4603,7 +5032,7 @@ function SplitCardFormInner({
|
|
|
4603
5032
|
borderTopLeftRadius: resolvedBorderRadius,
|
|
4604
5033
|
borderBottomLeftRadius: resolvedBorderRadius,
|
|
4605
5034
|
...(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
4606
|
-
}, children: /* @__PURE__ */ (0,
|
|
5035
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4607
5036
|
"input",
|
|
4608
5037
|
{
|
|
4609
5038
|
className: "flopay-shared-input",
|
|
@@ -4622,7 +5051,7 @@ function SplitCardFormInner({
|
|
|
4622
5051
|
style: inputFieldStyle()
|
|
4623
5052
|
}
|
|
4624
5053
|
) }),
|
|
4625
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0,
|
|
5054
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4626
5055
|
flex: 1,
|
|
4627
5056
|
backgroundColor: cardInputBg,
|
|
4628
5057
|
border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
|
|
@@ -4630,7 +5059,7 @@ function SplitCardFormInner({
|
|
|
4630
5059
|
borderTopRightRadius: resolvedBorderRadius,
|
|
4631
5060
|
borderBottomRightRadius: resolvedBorderRadius,
|
|
4632
5061
|
...(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
4633
|
-
}, children: stateOpts ? /* @__PURE__ */ (0,
|
|
5062
|
+
}, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
4634
5063
|
"select",
|
|
4635
5064
|
{
|
|
4636
5065
|
id: "flopay-billing-state",
|
|
@@ -4646,11 +5075,11 @@ function SplitCardFormInner({
|
|
|
4646
5075
|
"data-testid": "flopay-state",
|
|
4647
5076
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
4648
5077
|
children: [
|
|
4649
|
-
/* @__PURE__ */ (0,
|
|
4650
|
-
stateOpts.map((s) => /* @__PURE__ */ (0,
|
|
5078
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: (0, import_shared5.getStateLabel)(cc) }),
|
|
5079
|
+
stateOpts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: s.code, children: s.name }, s.code))
|
|
4651
5080
|
]
|
|
4652
5081
|
}
|
|
4653
|
-
) : /* @__PURE__ */ (0,
|
|
5082
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4654
5083
|
"input",
|
|
4655
5084
|
{
|
|
4656
5085
|
className: "flopay-shared-input",
|
|
@@ -4670,13 +5099,13 @@ function SplitCardFormInner({
|
|
|
4670
5099
|
}
|
|
4671
5100
|
) })
|
|
4672
5101
|
] }),
|
|
4673
|
-
((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0,
|
|
5102
|
+
((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
4674
5103
|
display: "flex",
|
|
4675
5104
|
flexDirection: avsLayoutProp === "column" ? "column" : "row",
|
|
4676
5105
|
gap: avsLayoutProp === "column" ? "0.5rem" : "0",
|
|
4677
5106
|
marginTop: "0.5rem"
|
|
4678
5107
|
}, children: [
|
|
4679
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0,
|
|
5108
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4680
5109
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
4681
5110
|
backgroundColor: cardInputBg,
|
|
4682
5111
|
borderTop: `1px solid ${resolvedBorder}`,
|
|
@@ -4685,7 +5114,7 @@ function SplitCardFormInner({
|
|
|
4685
5114
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
4686
5115
|
padding: "10px",
|
|
4687
5116
|
...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
|
|
4688
|
-
}, children: /* @__PURE__ */ (0,
|
|
5117
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4689
5118
|
"select",
|
|
4690
5119
|
{
|
|
4691
5120
|
id: "flopay-billing-country",
|
|
@@ -4702,20 +5131,20 @@ function SplitCardFormInner({
|
|
|
4702
5131
|
autoComplete: "billing country",
|
|
4703
5132
|
"data-testid": "flopay-country",
|
|
4704
5133
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
4705
|
-
children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0,
|
|
5134
|
+
children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("option", { value: c.code, children: [
|
|
4706
5135
|
c.flag,
|
|
4707
5136
|
" ",
|
|
4708
5137
|
c.name
|
|
4709
5138
|
] }, c.code))
|
|
4710
5139
|
}
|
|
4711
5140
|
) }),
|
|
4712
|
-
(0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0,
|
|
5141
|
+
(0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
4713
5142
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
4714
5143
|
backgroundColor: cardInputBg,
|
|
4715
5144
|
border: `1px solid ${zipBorderColor}`,
|
|
4716
5145
|
padding: "10px",
|
|
4717
5146
|
...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
|
|
4718
|
-
}, children: /* @__PURE__ */ (0,
|
|
5147
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4719
5148
|
"input",
|
|
4720
5149
|
{
|
|
4721
5150
|
className: "flopay-shared-input",
|
|
@@ -4739,7 +5168,7 @@ function SplitCardFormInner({
|
|
|
4739
5168
|
}
|
|
4740
5169
|
) })
|
|
4741
5170
|
] }),
|
|
4742
|
-
showPostcodeError && /* @__PURE__ */ (0,
|
|
5171
|
+
showPostcodeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4743
5172
|
"div",
|
|
4744
5173
|
{
|
|
4745
5174
|
id: "flopay-billing-postal-code-error",
|
|
@@ -4756,26 +5185,10 @@ function SplitCardFormInner({
|
|
|
4756
5185
|
)
|
|
4757
5186
|
] });
|
|
4758
5187
|
})() }),
|
|
4759
|
-
vaultActive && cardPreFormSlot && /* @__PURE__ */ (0,
|
|
5188
|
+
vaultActive && cardPreFormSlot && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
|
|
4760
5189
|
vaultActive && vaultCardFieldsNode,
|
|
4761
|
-
displayError && /* @__PURE__ */ (0,
|
|
4762
|
-
|
|
4763
|
-
padding: "0.625rem 0.875rem",
|
|
4764
|
-
background: "#FEF2F2",
|
|
4765
|
-
border: "1px solid #FECACA",
|
|
4766
|
-
borderRadius: "8px",
|
|
4767
|
-
color: "#991B1B",
|
|
4768
|
-
fontSize: "0.85rem",
|
|
4769
|
-
fontWeight: 600,
|
|
4770
|
-
display: "flex",
|
|
4771
|
-
alignItems: "center",
|
|
4772
|
-
gap: "0.5rem",
|
|
4773
|
-
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
4774
|
-
}, children: [
|
|
4775
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
4776
|
-
displayError
|
|
4777
|
-
] }),
|
|
4778
|
-
!vaultActive && (children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
5190
|
+
displayError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBanner, { margin: "0.75rem 0", styleOverride: bStyles.errorBanner, children: displayError }),
|
|
5191
|
+
!vaultActive && (children ?? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4779
5192
|
"button",
|
|
4780
5193
|
{
|
|
4781
5194
|
type: "submit",
|
|
@@ -4820,9 +5233,9 @@ function SplitCardFormInner({
|
|
|
4820
5233
|
const renderDirectPaypalGateDebug = (testId) => {
|
|
4821
5234
|
if (!debug) return null;
|
|
4822
5235
|
if (!showPayPal || !directPaypalConfigured) {
|
|
4823
|
-
return /* @__PURE__ */ (0,
|
|
5236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
|
|
4824
5237
|
}
|
|
4825
|
-
return /* @__PURE__ */ (0,
|
|
5238
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
4826
5239
|
"FloPay/DirectPayPal-debug (parent gate)",
|
|
4827
5240
|
` showPayPal=${showPayPal}`,
|
|
4828
5241
|
` directPaypalConfigured=${directPaypalConfigured}`,
|
|
@@ -4835,9 +5248,9 @@ function SplitCardFormInner({
|
|
|
4835
5248
|
const renderStripeGateDebug = (testId) => {
|
|
4836
5249
|
if (!debug) return null;
|
|
4837
5250
|
if (!showStripe || !stripeInstance) {
|
|
4838
|
-
return /* @__PURE__ */ (0,
|
|
5251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
|
|
4839
5252
|
}
|
|
4840
|
-
return /* @__PURE__ */ (0,
|
|
5253
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
4841
5254
|
"FloPay/Stripe-debug (parent gate)",
|
|
4842
5255
|
` showStripe=${showStripe}`,
|
|
4843
5256
|
` currency=${currency}`,
|
|
@@ -4866,11 +5279,11 @@ function SplitCardFormInner({
|
|
|
4866
5279
|
const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
4867
5280
|
const buttonsAnim = viewState === "expanding" || viewState === "apm-expanding" ? `flopay-buttons-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : viewState === "collapsing" || viewState === "apm-collapsing" ? `flopay-buttons-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : void 0;
|
|
4868
5281
|
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;
|
|
4869
|
-
return /* @__PURE__ */ (0,
|
|
4870
|
-
/* @__PURE__ */ (0,
|
|
4871
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
4872
|
-
/* @__PURE__ */ (0,
|
|
4873
|
-
/* @__PURE__ */ (0,
|
|
5282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
5283
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayKeyframes, {}),
|
|
5284
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
5285
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "grid" }, children: [
|
|
5286
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
4874
5287
|
"div",
|
|
4875
5288
|
{
|
|
4876
5289
|
"data-testid": "flopay-buttons-panel",
|
|
@@ -4887,8 +5300,8 @@ function SplitCardFormInner({
|
|
|
4887
5300
|
children: [
|
|
4888
5301
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
|
|
4889
5302
|
renderStripeGateDebug("flopay-stripe-gate-debug"),
|
|
4890
|
-
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0,
|
|
4891
|
-
paypalDirectRetry && /* @__PURE__ */ (0,
|
|
5303
|
+
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
5304
|
+
paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4892
5305
|
"div",
|
|
4893
5306
|
{
|
|
4894
5307
|
"data-testid": "flopay-paypal-direct-retry-notice",
|
|
@@ -4904,7 +5317,7 @@ function SplitCardFormInner({
|
|
|
4904
5317
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
4905
5318
|
}
|
|
4906
5319
|
),
|
|
4907
|
-
/* @__PURE__ */ (0,
|
|
5320
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4908
5321
|
DirectPayPalButton,
|
|
4909
5322
|
{
|
|
4910
5323
|
sessionId,
|
|
@@ -4931,7 +5344,7 @@ function SplitCardFormInner({
|
|
|
4931
5344
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
4932
5345
|
)
|
|
4933
5346
|
] }),
|
|
4934
|
-
shouldRenderStripePayPal && /* @__PURE__ */ (0,
|
|
5347
|
+
shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4935
5348
|
PayPalButtonInner,
|
|
4936
5349
|
{
|
|
4937
5350
|
sessionId,
|
|
@@ -4949,7 +5362,7 @@ function SplitCardFormInner({
|
|
|
4949
5362
|
placeholderBorderRadius: buttonBorderRadius
|
|
4950
5363
|
}
|
|
4951
5364
|
) }),
|
|
4952
|
-
shouldRenderWallets ? /* @__PURE__ */ (0,
|
|
5365
|
+
shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4953
5366
|
WalletButtonInner,
|
|
4954
5367
|
{
|
|
4955
5368
|
sessionId,
|
|
@@ -4966,8 +5379,8 @@ function SplitCardFormInner({
|
|
|
4966
5379
|
onLoadStateChange: setWalletLoadState,
|
|
4967
5380
|
placeholderBorderRadius: buttonBorderRadius
|
|
4968
5381
|
}
|
|
4969
|
-
) }) : shouldShowWallets ? /* @__PURE__ */ (0,
|
|
4970
|
-
shouldRenderPaymentElement && /* @__PURE__ */ (0,
|
|
5382
|
+
) }) : shouldShowWallets ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: buttonBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
5383
|
+
shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4971
5384
|
StripePaymentElementInner,
|
|
4972
5385
|
{
|
|
4973
5386
|
sessionId,
|
|
@@ -4999,7 +5412,7 @@ function SplitCardFormInner({
|
|
|
4999
5412
|
}
|
|
5000
5413
|
}
|
|
5001
5414
|
),
|
|
5002
|
-
showStripe && /* @__PURE__ */ (0,
|
|
5415
|
+
showStripe && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5003
5416
|
"button",
|
|
5004
5417
|
{
|
|
5005
5418
|
type: "button",
|
|
@@ -5055,50 +5468,34 @@ function SplitCardFormInner({
|
|
|
5055
5468
|
onMouseUp: (e) => {
|
|
5056
5469
|
e.currentTarget.style.transform = "scale(1)";
|
|
5057
5470
|
},
|
|
5058
|
-
children: /* @__PURE__ */ (0,
|
|
5471
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardButtonContentSlot, { content: cardButtonContent })
|
|
5059
5472
|
}
|
|
5060
5473
|
),
|
|
5061
|
-
displayError && viewState === "buttons" && /* @__PURE__ */ (0,
|
|
5062
|
-
margin: "0.25rem 0",
|
|
5063
|
-
padding: "0.625rem 0.875rem",
|
|
5064
|
-
background: "#FEF2F2",
|
|
5065
|
-
border: "1px solid #FECACA",
|
|
5066
|
-
borderRadius: "8px",
|
|
5067
|
-
color: "#991B1B",
|
|
5068
|
-
fontSize: "0.85rem",
|
|
5069
|
-
fontWeight: 600,
|
|
5070
|
-
display: "flex",
|
|
5071
|
-
alignItems: "center",
|
|
5072
|
-
gap: "0.5rem",
|
|
5073
|
-
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
5074
|
-
}, children: [
|
|
5075
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
5076
|
-
displayError
|
|
5077
|
-
] })
|
|
5474
|
+
displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBanner, { margin: "0.25rem 0", styleOverride: bStyles.errorBanner, children: displayError })
|
|
5078
5475
|
]
|
|
5079
5476
|
}
|
|
5080
5477
|
),
|
|
5081
|
-
showStripe && isCardView && /* @__PURE__ */ (0,
|
|
5478
|
+
showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5082
5479
|
gridArea: "1 / 1",
|
|
5083
5480
|
...cardAnim ? { animation: cardAnim } : {},
|
|
5084
5481
|
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
5085
5482
|
}, children: cardFormBlock }),
|
|
5086
|
-
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0,
|
|
5483
|
+
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5087
5484
|
gridArea: "1 / 1",
|
|
5088
5485
|
...apmAnim ? { animation: apmAnim } : {},
|
|
5089
5486
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
5090
|
-
}, children: /* @__PURE__ */ (0,
|
|
5487
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
5091
5488
|
backgroundColor: cardBg,
|
|
5092
5489
|
borderRadius: containerRadius,
|
|
5093
5490
|
...containerOverrides,
|
|
5094
5491
|
padding: containerPadding
|
|
5095
5492
|
}, children: [
|
|
5096
|
-
/* @__PURE__ */ (0,
|
|
5493
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
5097
5494
|
display: "flex",
|
|
5098
5495
|
alignItems: "center",
|
|
5099
5496
|
padding: "0.75rem 0 0.625rem"
|
|
5100
5497
|
}, children: [
|
|
5101
|
-
/* @__PURE__ */ (0,
|
|
5498
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
5102
5499
|
"button",
|
|
5103
5500
|
{
|
|
5104
5501
|
type: "button",
|
|
@@ -5121,7 +5518,7 @@ function SplitCardFormInner({
|
|
|
5121
5518
|
},
|
|
5122
5519
|
"aria-label": "Back to payment methods",
|
|
5123
5520
|
children: [
|
|
5124
|
-
/* @__PURE__ */ (0,
|
|
5521
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
5125
5522
|
display: "inline-flex",
|
|
5126
5523
|
alignItems: "center",
|
|
5127
5524
|
justifyContent: "center",
|
|
@@ -5131,12 +5528,12 @@ function SplitCardFormInner({
|
|
|
5131
5528
|
backgroundColor: "#f3f4f6",
|
|
5132
5529
|
transition: "background-color 0.15s",
|
|
5133
5530
|
...bStyles.backButtonIcon
|
|
5134
|
-
}, children: /* @__PURE__ */ (0,
|
|
5135
|
-
/* @__PURE__ */ (0,
|
|
5531
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
5532
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
5136
5533
|
]
|
|
5137
5534
|
}
|
|
5138
5535
|
),
|
|
5139
|
-
/* @__PURE__ */ (0,
|
|
5536
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5140
5537
|
flex: 1,
|
|
5141
5538
|
textAlign: "center",
|
|
5142
5539
|
fontWeight: 600,
|
|
@@ -5146,12 +5543,12 @@ function SplitCardFormInner({
|
|
|
5146
5543
|
...bStyles.title
|
|
5147
5544
|
}, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
|
|
5148
5545
|
] }),
|
|
5149
|
-
/* @__PURE__ */ (0,
|
|
5546
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5150
5547
|
import_react_stripe_js.Elements,
|
|
5151
5548
|
{
|
|
5152
5549
|
stripe: stripeInstance,
|
|
5153
5550
|
options: apmInlineOptions,
|
|
5154
|
-
children: /* @__PURE__ */ (0,
|
|
5551
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5155
5552
|
StripeMethodInlineForm,
|
|
5156
5553
|
{
|
|
5157
5554
|
method: expandedApmMethod,
|
|
@@ -5181,24 +5578,24 @@ function SplitCardFormInner({
|
|
|
5181
5578
|
] });
|
|
5182
5579
|
}
|
|
5183
5580
|
if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
|
|
5184
|
-
return /* @__PURE__ */ (0,
|
|
5185
|
-
/* @__PURE__ */ (0,
|
|
5186
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
5187
|
-
/* @__PURE__ */ (0,
|
|
5581
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
5582
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayKeyframes, {}),
|
|
5583
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
5584
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5188
5585
|
...apmAnim ? { animation: apmAnim } : {},
|
|
5189
5586
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
5190
|
-
}, children: /* @__PURE__ */ (0,
|
|
5587
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
5191
5588
|
backgroundColor: cardBg,
|
|
5192
5589
|
borderRadius: containerRadius,
|
|
5193
5590
|
...containerOverrides,
|
|
5194
5591
|
padding: containerPadding
|
|
5195
5592
|
}, children: [
|
|
5196
|
-
/* @__PURE__ */ (0,
|
|
5593
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
5197
5594
|
display: "flex",
|
|
5198
5595
|
alignItems: "center",
|
|
5199
5596
|
padding: "0.75rem 0 0.625rem"
|
|
5200
5597
|
}, children: [
|
|
5201
|
-
/* @__PURE__ */ (0,
|
|
5598
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
5202
5599
|
"button",
|
|
5203
5600
|
{
|
|
5204
5601
|
type: "button",
|
|
@@ -5221,7 +5618,7 @@ function SplitCardFormInner({
|
|
|
5221
5618
|
},
|
|
5222
5619
|
"aria-label": "Back to payment methods",
|
|
5223
5620
|
children: [
|
|
5224
|
-
/* @__PURE__ */ (0,
|
|
5621
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
5225
5622
|
display: "inline-flex",
|
|
5226
5623
|
alignItems: "center",
|
|
5227
5624
|
justifyContent: "center",
|
|
@@ -5231,12 +5628,12 @@ function SplitCardFormInner({
|
|
|
5231
5628
|
backgroundColor: "#f3f4f6",
|
|
5232
5629
|
transition: "background-color 0.15s",
|
|
5233
5630
|
...bStyles.backButtonIcon
|
|
5234
|
-
}, children: /* @__PURE__ */ (0,
|
|
5235
|
-
/* @__PURE__ */ (0,
|
|
5631
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
5632
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
5236
5633
|
]
|
|
5237
5634
|
}
|
|
5238
5635
|
),
|
|
5239
|
-
/* @__PURE__ */ (0,
|
|
5636
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
5240
5637
|
flex: 1,
|
|
5241
5638
|
textAlign: "center",
|
|
5242
5639
|
fontWeight: 600,
|
|
@@ -5246,12 +5643,12 @@ function SplitCardFormInner({
|
|
|
5246
5643
|
...bStyles.title
|
|
5247
5644
|
}, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
|
|
5248
5645
|
] }),
|
|
5249
|
-
/* @__PURE__ */ (0,
|
|
5646
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5250
5647
|
import_react_stripe_js.Elements,
|
|
5251
5648
|
{
|
|
5252
5649
|
stripe: stripeInstance,
|
|
5253
5650
|
options: apmInlineOptions,
|
|
5254
|
-
children: /* @__PURE__ */ (0,
|
|
5651
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5255
5652
|
StripeMethodInlineForm,
|
|
5256
5653
|
{
|
|
5257
5654
|
method: expandedApmMethod,
|
|
@@ -5279,14 +5676,14 @@ function SplitCardFormInner({
|
|
|
5279
5676
|
] }) })
|
|
5280
5677
|
] });
|
|
5281
5678
|
}
|
|
5282
|
-
return /* @__PURE__ */ (0,
|
|
5283
|
-
/* @__PURE__ */ (0,
|
|
5284
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
5285
|
-
/* @__PURE__ */ (0,
|
|
5679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
5680
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayKeyframes, {}),
|
|
5681
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
5682
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
5286
5683
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
|
|
5287
5684
|
renderStripeGateDebug("flopay-stripe-gate-debug-default"),
|
|
5288
|
-
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0,
|
|
5289
|
-
paypalDirectRetry && /* @__PURE__ */ (0,
|
|
5685
|
+
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
5686
|
+
paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5290
5687
|
"div",
|
|
5291
5688
|
{
|
|
5292
5689
|
"data-testid": "flopay-paypal-direct-retry-notice-default",
|
|
@@ -5302,7 +5699,7 @@ function SplitCardFormInner({
|
|
|
5302
5699
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
5303
5700
|
}
|
|
5304
5701
|
),
|
|
5305
|
-
/* @__PURE__ */ (0,
|
|
5702
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5306
5703
|
DirectPayPalButton,
|
|
5307
5704
|
{
|
|
5308
5705
|
sessionId,
|
|
@@ -5329,7 +5726,7 @@ function SplitCardFormInner({
|
|
|
5329
5726
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
5330
5727
|
)
|
|
5331
5728
|
] }),
|
|
5332
|
-
shouldRenderStripePayPal && /* @__PURE__ */ (0,
|
|
5729
|
+
shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5333
5730
|
PayPalButtonInner,
|
|
5334
5731
|
{
|
|
5335
5732
|
sessionId,
|
|
@@ -5347,7 +5744,7 @@ function SplitCardFormInner({
|
|
|
5347
5744
|
placeholderBorderRadius: buttonBorderRadius
|
|
5348
5745
|
}
|
|
5349
5746
|
) }),
|
|
5350
|
-
shouldRenderWallets && /* @__PURE__ */ (0,
|
|
5747
|
+
shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5351
5748
|
WalletButtonInner,
|
|
5352
5749
|
{
|
|
5353
5750
|
sessionId,
|
|
@@ -5365,7 +5762,7 @@ function SplitCardFormInner({
|
|
|
5365
5762
|
placeholderBorderRadius: buttonBorderRadius
|
|
5366
5763
|
}
|
|
5367
5764
|
) }),
|
|
5368
|
-
shouldRenderPaymentElement && /* @__PURE__ */ (0,
|
|
5765
|
+
shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5369
5766
|
StripePaymentElementInner,
|
|
5370
5767
|
{
|
|
5371
5768
|
sessionId,
|
|
@@ -5398,7 +5795,7 @@ function SplitCardFormInner({
|
|
|
5398
5795
|
}
|
|
5399
5796
|
)
|
|
5400
5797
|
] }),
|
|
5401
|
-
showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0,
|
|
5798
|
+
showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
5402
5799
|
display: "flex",
|
|
5403
5800
|
alignItems: "center",
|
|
5404
5801
|
gap: "0.75rem",
|
|
@@ -5406,9 +5803,9 @@ function SplitCardFormInner({
|
|
|
5406
5803
|
color: "#999",
|
|
5407
5804
|
fontSize: "0.85rem"
|
|
5408
5805
|
}, children: [
|
|
5409
|
-
/* @__PURE__ */ (0,
|
|
5410
|
-
/* @__PURE__ */ (0,
|
|
5411
|
-
/* @__PURE__ */ (0,
|
|
5806
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
|
|
5807
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "or pay with card" }),
|
|
5808
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
|
|
5412
5809
|
] }),
|
|
5413
5810
|
showStripe && cardFormBlock
|
|
5414
5811
|
] });
|
|
@@ -5438,6 +5835,9 @@ async function confirmResumeIntent(stripe, clientSecret, data, isSetupIntent) {
|
|
|
5438
5835
|
const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, data);
|
|
5439
5836
|
return { error, intent: paymentIntent ?? null };
|
|
5440
5837
|
}
|
|
5838
|
+
function withCheckoutMethod(error, checkoutMethod) {
|
|
5839
|
+
return Object.assign(error, { checkoutMethod });
|
|
5840
|
+
}
|
|
5441
5841
|
function getRedirectResultFromCheckoutProcessError(error) {
|
|
5442
5842
|
if (!error?.type || !error.threeDSecureToken) {
|
|
5443
5843
|
return null;
|
|
@@ -5659,7 +6059,7 @@ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment fai
|
|
|
5659
6059
|
const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
|
|
5660
6060
|
const rawMessage = error?.message ?? fallbackMessage;
|
|
5661
6061
|
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
5662
|
-
return
|
|
6062
|
+
return withCheckoutMethod(
|
|
5663
6063
|
new import_shared7.FloPayError(
|
|
5664
6064
|
message,
|
|
5665
6065
|
"api_error",
|
|
@@ -5667,7 +6067,7 @@ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment fai
|
|
|
5667
6067
|
code: error?.gatewayErrorCode
|
|
5668
6068
|
}
|
|
5669
6069
|
),
|
|
5670
|
-
|
|
6070
|
+
checkoutMethod
|
|
5671
6071
|
);
|
|
5672
6072
|
}
|
|
5673
6073
|
function resolveSavedPaymentReturnUrl(session) {
|
|
@@ -5753,7 +6153,7 @@ async function recover3DSRedirectResult({
|
|
|
5753
6153
|
return null;
|
|
5754
6154
|
}
|
|
5755
6155
|
try {
|
|
5756
|
-
const api = new import_js3.PaymentAPI(billingApiUrl);
|
|
6156
|
+
const api = new import_js3.PaymentAPI(billingApiUrl, { telemetry: false });
|
|
5757
6157
|
const unified = await api.getUnifiedCheckoutSession(sessionId, nonce);
|
|
5758
6158
|
const refreshedToken = unified.data.stripe?.clientSecret;
|
|
5759
6159
|
if (isStripePaymentIntentClientSecret(refreshedToken)) {
|
|
@@ -5772,7 +6172,8 @@ async function processSavedPaymentForMode({
|
|
|
5772
6172
|
session,
|
|
5773
6173
|
nonce,
|
|
5774
6174
|
tokenizedData,
|
|
5775
|
-
returnUrl
|
|
6175
|
+
returnUrl,
|
|
6176
|
+
telemetry
|
|
5776
6177
|
}) {
|
|
5777
6178
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
5778
6179
|
const resolvedSessionId = sessionId ?? session.id;
|
|
@@ -5783,7 +6184,10 @@ async function processSavedPaymentForMode({
|
|
|
5783
6184
|
const lastName = session.customer?.lastName ?? session.accountData?.lastName ?? "";
|
|
5784
6185
|
const country = session.customer?.country ?? session.accountData?.country ?? void 0;
|
|
5785
6186
|
const zip = session.customer?.zip ?? session.accountData?.zip ?? void 0;
|
|
5786
|
-
const api = new import_js3.PaymentAPI(
|
|
6187
|
+
const api = new import_js3.PaymentAPI(
|
|
6188
|
+
baseUrl,
|
|
6189
|
+
telemetry === false ? { telemetry: false } : void 0
|
|
6190
|
+
);
|
|
5787
6191
|
const response = await retryOnceOnFetchFailure(() => api.processPayment(customerId, {
|
|
5788
6192
|
sessionId: resolvedSessionId,
|
|
5789
6193
|
nonce: resolvedNonce,
|
|
@@ -5835,13 +6239,13 @@ async function processSavedPaymentForMode({
|
|
|
5835
6239
|
if (recoveredRedirect) {
|
|
5836
6240
|
return recoveredRedirect;
|
|
5837
6241
|
}
|
|
5838
|
-
throw
|
|
6242
|
+
throw withCheckoutMethod(
|
|
5839
6243
|
new import_shared7.FloPayError(
|
|
5840
6244
|
"Your card requires authentication. Please enter your payment details below.",
|
|
5841
6245
|
"api_error",
|
|
5842
6246
|
{ code: "authentication_required" }
|
|
5843
6247
|
),
|
|
5844
|
-
|
|
6248
|
+
"card"
|
|
5845
6249
|
);
|
|
5846
6250
|
}
|
|
5847
6251
|
throw new import_shared7.FloPayError(
|
|
@@ -5860,7 +6264,8 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5860
6264
|
billingApiUrl,
|
|
5861
6265
|
sessionId,
|
|
5862
6266
|
session,
|
|
5863
|
-
returnUrl
|
|
6267
|
+
returnUrl,
|
|
6268
|
+
telemetry
|
|
5864
6269
|
}) {
|
|
5865
6270
|
const stripe = flopay?.getRawProvider();
|
|
5866
6271
|
if (!stripe) {
|
|
@@ -5868,13 +6273,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5868
6273
|
}
|
|
5869
6274
|
if (redirectResult.type === "3ds_required") {
|
|
5870
6275
|
if (!attempt3DS || !redirectResult.threeDSecureToken) {
|
|
5871
|
-
throw
|
|
6276
|
+
throw withCheckoutMethod(
|
|
5872
6277
|
new import_shared7.FloPayError(
|
|
5873
6278
|
"Your card requires authentication. Please enter your payment details below.",
|
|
5874
6279
|
"api_error",
|
|
5875
6280
|
{ code: "authentication_required" }
|
|
5876
6281
|
),
|
|
5877
|
-
|
|
6282
|
+
"card"
|
|
5878
6283
|
);
|
|
5879
6284
|
}
|
|
5880
6285
|
const isSetupIntent = (0, import_shared7.isSetupIntentClientSecret)(redirectResult.threeDSecureToken);
|
|
@@ -5883,13 +6288,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5883
6288
|
const retrieved = await retrieveResumeIntent(stripe, redirectResult.threeDSecureToken, isSetupIntent);
|
|
5884
6289
|
if (retrieved) {
|
|
5885
6290
|
if (retrieved.error) {
|
|
5886
|
-
throw
|
|
6291
|
+
throw withCheckoutMethod(
|
|
5887
6292
|
new import_shared7.FloPayError(
|
|
5888
6293
|
retrieved.error.message ?? `Failed to retrieve 3DS ${isSetupIntent ? "setup" : "payment"} status.`,
|
|
5889
6294
|
"api_error",
|
|
5890
6295
|
{ code: retrieved.error.code }
|
|
5891
6296
|
),
|
|
5892
|
-
|
|
6297
|
+
"card"
|
|
5893
6298
|
);
|
|
5894
6299
|
}
|
|
5895
6300
|
const existingIntent = retrieved.intent;
|
|
@@ -5912,13 +6317,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5912
6317
|
) : null;
|
|
5913
6318
|
if (confirmed) {
|
|
5914
6319
|
if (confirmed.error) {
|
|
5915
|
-
throw
|
|
6320
|
+
throw withCheckoutMethod(
|
|
5916
6321
|
new import_shared7.FloPayError(
|
|
5917
6322
|
confirmed.error.message ?? "3DS authentication failed.",
|
|
5918
6323
|
"api_error",
|
|
5919
6324
|
{ code: confirmed.error.code }
|
|
5920
6325
|
),
|
|
5921
|
-
|
|
6326
|
+
"card"
|
|
5922
6327
|
);
|
|
5923
6328
|
}
|
|
5924
6329
|
paymentIntent = confirmed.intent;
|
|
@@ -5927,13 +6332,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5927
6332
|
clientSecret: redirectResult.threeDSecureToken
|
|
5928
6333
|
});
|
|
5929
6334
|
if (nextAction.error) {
|
|
5930
|
-
throw
|
|
6335
|
+
throw withCheckoutMethod(
|
|
5931
6336
|
new import_shared7.FloPayError(
|
|
5932
6337
|
nextAction.error.message ?? "3DS authentication failed.",
|
|
5933
6338
|
"api_error",
|
|
5934
6339
|
{ code: nextAction.error.code }
|
|
5935
6340
|
),
|
|
5936
|
-
|
|
6341
|
+
"card"
|
|
5937
6342
|
);
|
|
5938
6343
|
}
|
|
5939
6344
|
paymentIntent = (isSetupIntent ? nextAction.setupIntent : nextAction.paymentIntent) ?? null;
|
|
@@ -5943,6 +6348,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5943
6348
|
billingApiUrl,
|
|
5944
6349
|
sessionId,
|
|
5945
6350
|
session,
|
|
6351
|
+
telemetry,
|
|
5946
6352
|
tokenizedData: {
|
|
5947
6353
|
id: paymentIntent.id,
|
|
5948
6354
|
type: "card",
|
|
@@ -5964,20 +6370,21 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5964
6370
|
billingApiUrl,
|
|
5965
6371
|
sessionId,
|
|
5966
6372
|
session,
|
|
5967
|
-
returnUrl
|
|
6373
|
+
returnUrl,
|
|
6374
|
+
telemetry
|
|
5968
6375
|
});
|
|
5969
6376
|
}
|
|
5970
|
-
throw
|
|
6377
|
+
throw withCheckoutMethod(
|
|
5971
6378
|
new import_shared7.FloPayError("3DS authentication did not complete successfully.", "api_error"),
|
|
5972
|
-
|
|
6379
|
+
"card"
|
|
5973
6380
|
);
|
|
5974
6381
|
}
|
|
5975
6382
|
if (redirectResult.type === "paypal_redirect_required") {
|
|
5976
6383
|
const paypalStripe = (paypalFlopay ?? flopay)?.getRawProvider();
|
|
5977
6384
|
if (!paypalStripe) {
|
|
5978
|
-
throw
|
|
6385
|
+
throw withCheckoutMethod(
|
|
5979
6386
|
new import_shared7.FloPayError("PayPal is not available.", "api_error"),
|
|
5980
|
-
|
|
6387
|
+
"paypal"
|
|
5981
6388
|
);
|
|
5982
6389
|
}
|
|
5983
6390
|
if (redirectResult.paymentMethodId) {
|
|
@@ -5985,13 +6392,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5985
6392
|
clientSecret: redirectResult.threeDSecureToken
|
|
5986
6393
|
});
|
|
5987
6394
|
if (error2) {
|
|
5988
|
-
throw
|
|
6395
|
+
throw withCheckoutMethod(
|
|
5989
6396
|
new import_shared7.FloPayError(
|
|
5990
6397
|
error2.message ?? "PayPal authorization failed.",
|
|
5991
6398
|
"api_error",
|
|
5992
6399
|
{ code: error2.code }
|
|
5993
6400
|
),
|
|
5994
|
-
|
|
6401
|
+
"paypal"
|
|
5995
6402
|
);
|
|
5996
6403
|
}
|
|
5997
6404
|
return {
|
|
@@ -6008,13 +6415,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
6008
6415
|
redirect: "if_required"
|
|
6009
6416
|
});
|
|
6010
6417
|
if (error) {
|
|
6011
|
-
throw
|
|
6418
|
+
throw withCheckoutMethod(
|
|
6012
6419
|
new import_shared7.FloPayError(
|
|
6013
6420
|
error.message ?? "PayPal authorization failed.",
|
|
6014
6421
|
"api_error",
|
|
6015
6422
|
{ code: error.code }
|
|
6016
6423
|
),
|
|
6017
|
-
|
|
6424
|
+
"paypal"
|
|
6018
6425
|
);
|
|
6019
6426
|
}
|
|
6020
6427
|
return {
|
|
@@ -6070,7 +6477,8 @@ async function loadSavedPaymentProviders({
|
|
|
6070
6477
|
publishableKey,
|
|
6071
6478
|
paypalPublishableKey,
|
|
6072
6479
|
billingApiUrl,
|
|
6073
|
-
locale
|
|
6480
|
+
locale,
|
|
6481
|
+
telemetry
|
|
6074
6482
|
}) {
|
|
6075
6483
|
if (!publishableKey) {
|
|
6076
6484
|
return { flopay: null, paypalFlopay: null };
|
|
@@ -6079,11 +6487,13 @@ async function loadSavedPaymentProviders({
|
|
|
6079
6487
|
const [instance, paypalInstanceOrError] = await Promise.all([
|
|
6080
6488
|
(0, import_js3.loadFloPay)(publishableKey, {
|
|
6081
6489
|
billingApiUrl,
|
|
6082
|
-
locale
|
|
6490
|
+
locale,
|
|
6491
|
+
telemetry
|
|
6083
6492
|
}),
|
|
6084
6493
|
needsSeparatePaypal ? (0, import_js3.loadFloPay)(paypalPublishableKey, {
|
|
6085
6494
|
billingApiUrl,
|
|
6086
|
-
locale
|
|
6495
|
+
locale,
|
|
6496
|
+
telemetry
|
|
6087
6497
|
}).catch((err) => {
|
|
6088
6498
|
console.warn("[FloPay] Failed to load PayPal Stripe instance:", err);
|
|
6089
6499
|
return null;
|
|
@@ -6096,13 +6506,40 @@ async function loadSavedPaymentProviders({
|
|
|
6096
6506
|
}
|
|
6097
6507
|
|
|
6098
6508
|
// src/flopay-checkout.tsx
|
|
6099
|
-
var
|
|
6509
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
6100
6510
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
|
|
6101
6511
|
var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
|
|
6102
6512
|
var sessionInflightMap = /* @__PURE__ */ new Map();
|
|
6103
6513
|
function sleep(ms) {
|
|
6104
6514
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6105
6515
|
}
|
|
6516
|
+
function createStandaloneTelemetryReporter(billingApiUrl, enabled, context) {
|
|
6517
|
+
const reporter = createTelemetryBridge({
|
|
6518
|
+
billingApiUrl,
|
|
6519
|
+
sdkPackage: "@flopay/react",
|
|
6520
|
+
sdkVersion: import_shared8.SDK_VERSION,
|
|
6521
|
+
enabled: enabled !== false
|
|
6522
|
+
});
|
|
6523
|
+
reporter.beginCheckout(context);
|
|
6524
|
+
return reporter;
|
|
6525
|
+
}
|
|
6526
|
+
function finishStandaloneTelemetry(reporter) {
|
|
6527
|
+
void reporter.flush().catch(() => {
|
|
6528
|
+
}).finally(() => reporter.destroy());
|
|
6529
|
+
}
|
|
6530
|
+
function reportStandaloneTelemetryError(billingApiUrl, enabled, context, errorCode, stage) {
|
|
6531
|
+
const reporter = createStandaloneTelemetryReporter(billingApiUrl, enabled, context);
|
|
6532
|
+
reporter.error({
|
|
6533
|
+
errorCode,
|
|
6534
|
+
stage,
|
|
6535
|
+
paymentMethodCategory: "unknown",
|
|
6536
|
+
...stage === "session_read" ? { requestCategory: "session_read" } : {}
|
|
6537
|
+
});
|
|
6538
|
+
finishStandaloneTelemetry(reporter);
|
|
6539
|
+
}
|
|
6540
|
+
function isExpectedExistingSessionError(error) {
|
|
6541
|
+
return error.type === "validation_error" || error.code === "checkout_session_not_found" || error.code === "checkout_session_expired" || error.code === "checkout_session_completed" || error.code === "session_auto_completed";
|
|
6542
|
+
}
|
|
6106
6543
|
function resolveDirectPaypalConfig(unified) {
|
|
6107
6544
|
const clientId = unified?.data.paypal?.publishableKey;
|
|
6108
6545
|
if (!clientId) return void 0;
|
|
@@ -6207,6 +6644,7 @@ function FloPayCheckout({
|
|
|
6207
6644
|
nonce: nonceProp,
|
|
6208
6645
|
createSession: createSessionParams,
|
|
6209
6646
|
billingApiUrl,
|
|
6647
|
+
telemetry,
|
|
6210
6648
|
appearance: appearanceOverride,
|
|
6211
6649
|
locale,
|
|
6212
6650
|
loading: loadingNode,
|
|
@@ -6246,41 +6684,51 @@ function FloPayCheckout({
|
|
|
6246
6684
|
onSessionCompleted
|
|
6247
6685
|
}) {
|
|
6248
6686
|
const resolvedBillingUrl = (0, import_shared8.resolveBillingApiUrl)(billingApiUrl);
|
|
6249
|
-
const themeBundle = (0,
|
|
6687
|
+
const themeBundle = (0, import_react11.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
|
|
6250
6688
|
const appearance = appearanceOverride ?? themeBundle?.appearance;
|
|
6251
6689
|
const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
|
|
6252
6690
|
const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
|
|
6253
|
-
const [unified, setUnified] = (0,
|
|
6254
|
-
const [flopay, setFloPay] = (0,
|
|
6255
|
-
const flopayRef = (0,
|
|
6256
|
-
const [paypalFlopay, setPaypalFloPay] = (0,
|
|
6257
|
-
const paypalFlopayRef = (0,
|
|
6258
|
-
const [session, setSession] = (0,
|
|
6259
|
-
const [resolvedSessionId, setResolvedSessionId] = (0,
|
|
6691
|
+
const [unified, setUnified] = (0, import_react11.useState)(null);
|
|
6692
|
+
const [flopay, setFloPay] = (0, import_react11.useState)(null);
|
|
6693
|
+
const flopayRef = (0, import_react11.useRef)(null);
|
|
6694
|
+
const [paypalFlopay, setPaypalFloPay] = (0, import_react11.useState)(null);
|
|
6695
|
+
const paypalFlopayRef = (0, import_react11.useRef)(null);
|
|
6696
|
+
const [session, setSession] = (0, import_react11.useState)(null);
|
|
6697
|
+
const [resolvedSessionId, setResolvedSessionId] = (0, import_react11.useState)(sessionIdProp ?? "");
|
|
6260
6698
|
const activeSessionId = sessionIdProp ?? resolvedSessionId;
|
|
6261
6699
|
const initSessionDependency = createSessionParams ? "" : activeSessionId;
|
|
6262
|
-
const [isLoading, setIsLoading] = (0,
|
|
6263
|
-
const [loadError, setLoadError] = (0,
|
|
6264
|
-
const [currentMode, setCurrentMode] = (0,
|
|
6265
|
-
const [confirmProcessing, setConfirmProcessing] = (0,
|
|
6266
|
-
const [modeError, setModeError] = (0,
|
|
6267
|
-
const [modeOverlayStatus, setModeOverlayStatus] = (0,
|
|
6268
|
-
const [modeOverlayError, setModeOverlayError] = (0,
|
|
6269
|
-
const [createSessionPatch, setCreateSessionPatch] = (0,
|
|
6270
|
-
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0,
|
|
6271
|
-
const [cardBootstrapPending, setCardBootstrapPending] = (0,
|
|
6272
|
-
const autoCheckoutAttempted = (0,
|
|
6273
|
-
const paypalResumeAttempted = (0,
|
|
6274
|
-
const savedPaymentKeysRef = (0,
|
|
6275
|
-
const
|
|
6700
|
+
const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
|
|
6701
|
+
const [loadError, setLoadError] = (0, import_react11.useState)(null);
|
|
6702
|
+
const [currentMode, setCurrentMode] = (0, import_react11.useState)("full");
|
|
6703
|
+
const [confirmProcessing, setConfirmProcessing] = (0, import_react11.useState)(false);
|
|
6704
|
+
const [modeError, setModeError] = (0, import_react11.useState)(initialErrorMessage);
|
|
6705
|
+
const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react11.useState)(null);
|
|
6706
|
+
const [modeOverlayError, setModeOverlayError] = (0, import_react11.useState)(null);
|
|
6707
|
+
const [createSessionPatch, setCreateSessionPatch] = (0, import_react11.useState)(void 0);
|
|
6708
|
+
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react11.useState)("");
|
|
6709
|
+
const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react11.useState)(false);
|
|
6710
|
+
const autoCheckoutAttempted = (0, import_react11.useRef)(false);
|
|
6711
|
+
const paypalResumeAttempted = (0, import_react11.useRef)(false);
|
|
6712
|
+
const savedPaymentKeysRef = (0, import_react11.useRef)(null);
|
|
6713
|
+
const telemetryCheckoutContext = (0, import_react11.useMemo)(() => ({
|
|
6714
|
+
checkoutMode: checkoutModeProp ?? currentMode,
|
|
6715
|
+
layout: children ? "unknown" : layout === "buttons" ? "buttons" : "embedded"
|
|
6716
|
+
}), [checkoutModeProp, children, currentMode, layout]);
|
|
6717
|
+
const onCompleteRef = (0, import_react11.useRef)(onComplete);
|
|
6276
6718
|
onCompleteRef.current = onComplete;
|
|
6277
|
-
const onErrorRef = (0,
|
|
6719
|
+
const onErrorRef = (0, import_react11.useRef)(onError);
|
|
6278
6720
|
onErrorRef.current = onError;
|
|
6279
|
-
const onDeclineRef = (0,
|
|
6721
|
+
const onDeclineRef = (0, import_react11.useRef)(onDecline);
|
|
6280
6722
|
onDeclineRef.current = onDecline;
|
|
6281
|
-
|
|
6723
|
+
(0, import_react11.useEffect)(() => {
|
|
6724
|
+
getFloPayTelemetryBridge(flopay)?.setCheckoutContext(telemetryCheckoutContext);
|
|
6725
|
+
if (paypalFlopay && paypalFlopay !== flopay) {
|
|
6726
|
+
getFloPayTelemetryBridge(paypalFlopay)?.setCheckoutContext(telemetryCheckoutContext);
|
|
6727
|
+
}
|
|
6728
|
+
}, [flopay, paypalFlopay, telemetryCheckoutContext]);
|
|
6729
|
+
const onSessionCompletedRef = (0, import_react11.useRef)(onSessionCompleted);
|
|
6282
6730
|
onSessionCompletedRef.current = onSessionCompleted;
|
|
6283
|
-
(0,
|
|
6731
|
+
(0, import_react11.useEffect)(() => {
|
|
6284
6732
|
console.info("[FloPay] Checkout initialized", {
|
|
6285
6733
|
sdk_version: import_shared8.SDK_VERSION,
|
|
6286
6734
|
checkout_type: checkoutType,
|
|
@@ -6288,49 +6736,139 @@ function FloPayCheckout({
|
|
|
6288
6736
|
billing_api_url: resolvedBillingUrl
|
|
6289
6737
|
});
|
|
6290
6738
|
}, [checkoutLayout, checkoutType, resolvedBillingUrl]);
|
|
6291
|
-
const baseCreateSessionHash = (0,
|
|
6739
|
+
const baseCreateSessionHash = (0, import_react11.useMemo)(
|
|
6292
6740
|
() => createSessionParams ? hashCreateParams(createSessionParams) : "",
|
|
6293
6741
|
[createSessionParams]
|
|
6294
6742
|
);
|
|
6295
|
-
const activeCreateSessionPatch = (0,
|
|
6743
|
+
const activeCreateSessionPatch = (0, import_react11.useMemo)(
|
|
6296
6744
|
() => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
|
|
6297
6745
|
[createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
|
|
6298
6746
|
);
|
|
6299
|
-
const effectiveCreateSessionBase = (0,
|
|
6747
|
+
const effectiveCreateSessionBase = (0, import_react11.useMemo)(
|
|
6300
6748
|
() => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
|
|
6301
6749
|
[createSessionParams, activeCreateSessionPatch]
|
|
6302
6750
|
);
|
|
6303
6751
|
const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
|
|
6304
|
-
const effectiveCreateSession = (0,
|
|
6752
|
+
const effectiveCreateSession = (0, import_react11.useMemo)(
|
|
6305
6753
|
() => effectiveCreateSessionBase ? {
|
|
6306
6754
|
...effectiveCreateSessionBase,
|
|
6307
6755
|
checkoutMode: effectiveCreateSessionMode
|
|
6308
6756
|
} : void 0,
|
|
6309
6757
|
[effectiveCreateSessionBase, effectiveCreateSessionMode]
|
|
6310
6758
|
);
|
|
6311
|
-
(0,
|
|
6759
|
+
(0, import_react11.useEffect)(() => {
|
|
6312
6760
|
setCreateSessionPatch(void 0);
|
|
6313
6761
|
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
6314
6762
|
}, [baseCreateSessionHash]);
|
|
6315
|
-
(0,
|
|
6763
|
+
(0, import_react11.useEffect)(() => {
|
|
6316
6764
|
setModeError(initialErrorMessage);
|
|
6317
6765
|
}, [initialErrorMessage]);
|
|
6318
|
-
const emitDecline = (0,
|
|
6766
|
+
const emitDecline = (0, import_react11.useCallback)(
|
|
6319
6767
|
(method, input, overrides) => {
|
|
6320
|
-
|
|
6768
|
+
invokeMerchantCallback(() => {
|
|
6769
|
+
onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
|
|
6770
|
+
});
|
|
6321
6771
|
},
|
|
6322
|
-
[]
|
|
6772
|
+
[invokeMerchantCallback]
|
|
6323
6773
|
);
|
|
6324
|
-
const runSavedPaymentFlow = (0,
|
|
6774
|
+
const runSavedPaymentFlow = (0, import_react11.useCallback)(
|
|
6325
6775
|
async (sess, options) => {
|
|
6326
6776
|
setModeError(null);
|
|
6327
6777
|
setModeOverlayError(null);
|
|
6328
6778
|
setModeOverlayStatus("processing");
|
|
6329
6779
|
const activeSessionId2 = options?.sessionId ?? sess.id;
|
|
6780
|
+
const activeFloPay = flopayRef.current ?? paypalFlopayRef.current;
|
|
6781
|
+
const activeTelemetry = getFloPayTelemetryBridge(activeFloPay);
|
|
6782
|
+
const standaloneTelemetry = activeFloPay ? null : createStandaloneTelemetryReporter(
|
|
6783
|
+
resolvedBillingUrl,
|
|
6784
|
+
telemetry,
|
|
6785
|
+
telemetryCheckoutContext
|
|
6786
|
+
);
|
|
6787
|
+
const telemetrySource = {
|
|
6788
|
+
log: (input) => {
|
|
6789
|
+
if (activeTelemetry) activeTelemetry.log(input);
|
|
6790
|
+
else standaloneTelemetry?.log(input);
|
|
6791
|
+
},
|
|
6792
|
+
error: (input) => {
|
|
6793
|
+
if (activeTelemetry) activeTelemetry.error(input);
|
|
6794
|
+
else standaloneTelemetry?.error(input);
|
|
6795
|
+
},
|
|
6796
|
+
terminal: (input) => {
|
|
6797
|
+
if (activeTelemetry) activeTelemetry.terminal(input);
|
|
6798
|
+
else standaloneTelemetry?.terminal(input);
|
|
6799
|
+
},
|
|
6800
|
+
performance: (input) => {
|
|
6801
|
+
if (activeTelemetry) activeTelemetry.performance(input);
|
|
6802
|
+
else standaloneTelemetry?.performance(input);
|
|
6803
|
+
},
|
|
6804
|
+
now: () => activeTelemetry?.now() ?? standaloneTelemetry?.now() ?? 0,
|
|
6805
|
+
elapsed: (startedAt) => activeTelemetry?.elapsed(startedAt) ?? Math.max(0, (standaloneTelemetry?.now() ?? startedAt) - startedAt)
|
|
6806
|
+
};
|
|
6807
|
+
const processingStartedAt = telemetrySource.now();
|
|
6808
|
+
let recoveryFlow = Boolean(
|
|
6809
|
+
options?.initialAutoProcessingError || options?.initialAutoProcessingPending
|
|
6810
|
+
);
|
|
6811
|
+
let recoveryStarted = false;
|
|
6812
|
+
let recoveryStartedAt;
|
|
6813
|
+
const startRecovery = () => {
|
|
6814
|
+
if (recoveryStarted) return;
|
|
6815
|
+
recoveryStarted = true;
|
|
6816
|
+
recoveryFlow = true;
|
|
6817
|
+
recoveryStartedAt = telemetrySource.now();
|
|
6818
|
+
telemetrySource.log({
|
|
6819
|
+
name: "checkout.recovery.started",
|
|
6820
|
+
stage: "recovery",
|
|
6821
|
+
paymentMethodCategory: "saved"
|
|
6822
|
+
});
|
|
6823
|
+
telemetrySource.log({
|
|
6824
|
+
name: "operation.recovery.started",
|
|
6825
|
+
stage: "recovery",
|
|
6826
|
+
paymentMethodCategory: "saved"
|
|
6827
|
+
});
|
|
6828
|
+
};
|
|
6829
|
+
let processingFinished = false;
|
|
6830
|
+
const finishProcessing = () => {
|
|
6831
|
+
if (processingFinished) return;
|
|
6832
|
+
processingFinished = true;
|
|
6833
|
+
telemetrySource.log({
|
|
6834
|
+
name: "payment.processing.completed",
|
|
6835
|
+
stage: "processing",
|
|
6836
|
+
paymentMethodCategory: "saved"
|
|
6837
|
+
});
|
|
6838
|
+
telemetrySource.performance({
|
|
6839
|
+
stage: "processing",
|
|
6840
|
+
durationMs: telemetrySource.elapsed(processingStartedAt),
|
|
6841
|
+
durationMode: "machine",
|
|
6842
|
+
paymentMethodCategory: "saved"
|
|
6843
|
+
});
|
|
6844
|
+
if (recoveryStartedAt !== void 0) {
|
|
6845
|
+
telemetrySource.performance({
|
|
6846
|
+
stage: "recovery",
|
|
6847
|
+
durationMs: telemetrySource.elapsed(recoveryStartedAt),
|
|
6848
|
+
durationMode: "machine",
|
|
6849
|
+
paymentMethodCategory: "saved"
|
|
6850
|
+
});
|
|
6851
|
+
}
|
|
6852
|
+
};
|
|
6853
|
+
telemetrySource.log({
|
|
6854
|
+
name: "payment.method.selected",
|
|
6855
|
+
stage: "processing",
|
|
6856
|
+
paymentMethodCategory: "saved"
|
|
6857
|
+
});
|
|
6858
|
+
telemetrySource.log({
|
|
6859
|
+
name: "payment.processing.started",
|
|
6860
|
+
stage: "processing",
|
|
6861
|
+
paymentMethodCategory: "saved"
|
|
6862
|
+
});
|
|
6863
|
+
if (recoveryFlow) {
|
|
6864
|
+
startRecovery();
|
|
6865
|
+
}
|
|
6866
|
+
let completionCallback;
|
|
6330
6867
|
try {
|
|
6331
6868
|
const redirectResult = getRedirectResultFromCheckoutProcessError(options?.initialAutoProcessingError);
|
|
6332
6869
|
let paymentResult;
|
|
6333
6870
|
if (redirectResult) {
|
|
6871
|
+
startRecovery();
|
|
6334
6872
|
if (redirectResult.type === "paypal_redirect_required" && savedPaymentKeysRef.current?.publishableKey) {
|
|
6335
6873
|
persistPayPalResumeState({
|
|
6336
6874
|
sessionId: activeSessionId2,
|
|
@@ -6344,13 +6882,14 @@ function FloPayCheckout({
|
|
|
6344
6882
|
attempt3DS: options?.attempt3DS,
|
|
6345
6883
|
billingApiUrl: resolvedBillingUrl,
|
|
6346
6884
|
sessionId: activeSessionId2,
|
|
6347
|
-
session: sess
|
|
6885
|
+
session: sess,
|
|
6886
|
+
telemetry: false
|
|
6348
6887
|
});
|
|
6349
6888
|
if (redirectResult.type === "paypal_redirect_required") {
|
|
6350
6889
|
clearPayPalResumeState();
|
|
6351
6890
|
}
|
|
6352
6891
|
} else if (options?.initialAutoProcessingPending) {
|
|
6353
|
-
const api = new import_js4.PaymentAPI(resolvedBillingUrl);
|
|
6892
|
+
const api = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
|
|
6354
6893
|
const completed = await api.waitForCheckoutSessionCompletion(options.initialAutoProcessingPending.sessionId, {
|
|
6355
6894
|
initialDelayMs: options.initialAutoProcessingPending.retryAfterMs
|
|
6356
6895
|
});
|
|
@@ -6378,11 +6917,13 @@ function FloPayCheckout({
|
|
|
6378
6917
|
const result = await processSavedPaymentForMode({
|
|
6379
6918
|
billingApiUrl: resolvedBillingUrl,
|
|
6380
6919
|
sessionId: activeSessionId2,
|
|
6381
|
-
session: sess
|
|
6920
|
+
session: sess,
|
|
6921
|
+
telemetry: false
|
|
6382
6922
|
});
|
|
6383
6923
|
if (result.type === "success") {
|
|
6384
6924
|
paymentResult = result.result;
|
|
6385
6925
|
} else {
|
|
6926
|
+
startRecovery();
|
|
6386
6927
|
if (result.type === "paypal_redirect_required" && savedPaymentKeysRef.current?.publishableKey) {
|
|
6387
6928
|
persistPayPalResumeState({
|
|
6388
6929
|
sessionId: activeSessionId2,
|
|
@@ -6396,7 +6937,8 @@ function FloPayCheckout({
|
|
|
6396
6937
|
attempt3DS: options?.attempt3DS,
|
|
6397
6938
|
billingApiUrl: resolvedBillingUrl,
|
|
6398
6939
|
sessionId: activeSessionId2,
|
|
6399
|
-
session: sess
|
|
6940
|
+
session: sess,
|
|
6941
|
+
telemetry: false
|
|
6400
6942
|
});
|
|
6401
6943
|
if (result.type === "paypal_redirect_required") {
|
|
6402
6944
|
clearPayPalResumeState();
|
|
@@ -6404,20 +6946,57 @@ function FloPayCheckout({
|
|
|
6404
6946
|
}
|
|
6405
6947
|
}
|
|
6406
6948
|
if (activeSessionId2) markSessionRecentlyCompleted(activeSessionId2);
|
|
6949
|
+
finishProcessing();
|
|
6950
|
+
if (recoveryFlow) {
|
|
6951
|
+
telemetrySource.log({
|
|
6952
|
+
name: "checkout.recovery.completed",
|
|
6953
|
+
stage: "recovery",
|
|
6954
|
+
paymentMethodCategory: "saved"
|
|
6955
|
+
});
|
|
6956
|
+
telemetrySource.log({
|
|
6957
|
+
name: "operation.recovery.completed",
|
|
6958
|
+
stage: "recovery",
|
|
6959
|
+
paymentMethodCategory: "saved"
|
|
6960
|
+
});
|
|
6961
|
+
}
|
|
6962
|
+
telemetrySource.terminal({
|
|
6963
|
+
outcome: "payment_succeeded",
|
|
6964
|
+
paymentMethodCategory: "saved"
|
|
6965
|
+
});
|
|
6407
6966
|
setModeOverlayStatus("success");
|
|
6408
6967
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
6409
|
-
onCompleteRef.current?.(paymentResult);
|
|
6410
|
-
return true;
|
|
6968
|
+
completionCallback = () => onCompleteRef.current?.(paymentResult);
|
|
6411
6969
|
} catch (err) {
|
|
6412
6970
|
const floPayErr = normalizeSavedPaymentError(err);
|
|
6413
6971
|
const method = floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD;
|
|
6414
6972
|
setModeError(floPayErr.message);
|
|
6415
6973
|
setModeOverlayError(floPayErr.message);
|
|
6416
6974
|
if (options?.fallbackToFull) {
|
|
6975
|
+
telemetrySource.log({
|
|
6976
|
+
name: "operation.fallback",
|
|
6977
|
+
stage: "recovery",
|
|
6978
|
+
paymentMethodCategory: "saved"
|
|
6979
|
+
});
|
|
6417
6980
|
setCurrentMode("full");
|
|
6418
6981
|
replaceCheckoutModeQueryParam("full");
|
|
6419
6982
|
}
|
|
6420
|
-
|
|
6983
|
+
finishProcessing();
|
|
6984
|
+
const expectedDecline = Boolean(
|
|
6985
|
+
floPayErr.declineCode || floPayErr.code?.toLowerCase().includes("declin")
|
|
6986
|
+
);
|
|
6987
|
+
if (expectedDecline) {
|
|
6988
|
+
telemetrySource.terminal({
|
|
6989
|
+
outcome: "payment_declined",
|
|
6990
|
+
paymentMethodCategory: "saved"
|
|
6991
|
+
});
|
|
6992
|
+
} else {
|
|
6993
|
+
telemetrySource.error({
|
|
6994
|
+
errorCode: recoveryFlow ? "RECOVERY_FAILED" : "PAYMENT_PROCESSING_FAILED",
|
|
6995
|
+
stage: recoveryFlow ? "recovery" : "processing",
|
|
6996
|
+
paymentMethodCategory: "saved"
|
|
6997
|
+
});
|
|
6998
|
+
}
|
|
6999
|
+
invokeMerchantCallback(() => onErrorRef.current?.(floPayErr));
|
|
6421
7000
|
emitDecline(method, floPayErr, {
|
|
6422
7001
|
code: floPayErr.code,
|
|
6423
7002
|
declineCode: floPayErr.declineCode
|
|
@@ -6427,19 +7006,38 @@ function FloPayCheckout({
|
|
|
6427
7006
|
sleep(PROCESSING_OVERLAY_ERROR_DELAY_MS),
|
|
6428
7007
|
options?.ensureProvidersReady ? options.ensureProvidersReady() : Promise.resolve()
|
|
6429
7008
|
]);
|
|
7009
|
+
if (recoveryFlow) {
|
|
7010
|
+
telemetrySource.log({
|
|
7011
|
+
name: "checkout.recovery.completed",
|
|
7012
|
+
stage: "recovery",
|
|
7013
|
+
paymentMethodCategory: "saved"
|
|
7014
|
+
});
|
|
7015
|
+
telemetrySource.log({
|
|
7016
|
+
name: "operation.recovery.completed",
|
|
7017
|
+
stage: "recovery",
|
|
7018
|
+
paymentMethodCategory: "saved"
|
|
7019
|
+
});
|
|
7020
|
+
}
|
|
6430
7021
|
return false;
|
|
6431
7022
|
} finally {
|
|
7023
|
+
finishProcessing();
|
|
7024
|
+
if (standaloneTelemetry) finishStandaloneTelemetry(standaloneTelemetry);
|
|
6432
7025
|
setModeOverlayStatus(null);
|
|
6433
7026
|
setModeOverlayError(null);
|
|
6434
7027
|
}
|
|
7028
|
+
invokeMerchantCallback(completionCallback);
|
|
7029
|
+
return true;
|
|
6435
7030
|
},
|
|
6436
7031
|
[
|
|
6437
7032
|
emitDecline,
|
|
7033
|
+
invokeMerchantCallback,
|
|
6438
7034
|
normalizeSavedPaymentError,
|
|
6439
|
-
resolvedBillingUrl
|
|
7035
|
+
resolvedBillingUrl,
|
|
7036
|
+
telemetry,
|
|
7037
|
+
telemetryCheckoutContext
|
|
6440
7038
|
]
|
|
6441
7039
|
);
|
|
6442
|
-
(0,
|
|
7040
|
+
(0, import_react11.useEffect)(() => {
|
|
6443
7041
|
if (typeof window === "undefined" || paypalResumeAttempted.current) {
|
|
6444
7042
|
return;
|
|
6445
7043
|
}
|
|
@@ -6454,6 +7052,8 @@ function FloPayCheckout({
|
|
|
6454
7052
|
}
|
|
6455
7053
|
paypalResumeAttempted.current = true;
|
|
6456
7054
|
void (async () => {
|
|
7055
|
+
let resumeTelemetry;
|
|
7056
|
+
let redirectResumeStartedAt = 0;
|
|
6457
7057
|
setModeError(null);
|
|
6458
7058
|
setModeOverlayError(null);
|
|
6459
7059
|
setModeOverlayStatus("processing");
|
|
@@ -6461,7 +7061,11 @@ function FloPayCheckout({
|
|
|
6461
7061
|
try {
|
|
6462
7062
|
if (params.get("redirect_status") === "failed") {
|
|
6463
7063
|
throw Object.assign(
|
|
6464
|
-
new import_shared8.FloPayError(
|
|
7064
|
+
new import_shared8.FloPayError(
|
|
7065
|
+
"PayPal payment was declined. Please try again.",
|
|
7066
|
+
"api_error",
|
|
7067
|
+
{ declineCode: "paypal_redirect_failed" }
|
|
7068
|
+
),
|
|
6465
7069
|
{ checkoutMethod: "paypal" }
|
|
6466
7070
|
);
|
|
6467
7071
|
}
|
|
@@ -6472,7 +7076,22 @@ function FloPayCheckout({
|
|
|
6472
7076
|
publishableKey: resumeState.publishableKey,
|
|
6473
7077
|
paypalPublishableKey: resumeState.paypalPublishableKey,
|
|
6474
7078
|
billingApiUrl: resolvedBillingUrl,
|
|
6475
|
-
locale
|
|
7079
|
+
locale,
|
|
7080
|
+
telemetry
|
|
7081
|
+
});
|
|
7082
|
+
resumeTelemetry = getFloPayTelemetryBridge(resumePaypalFlopay ?? resumeFlopay);
|
|
7083
|
+
redirectResumeStartedAt = resumeTelemetry?.now() ?? 0;
|
|
7084
|
+
resumeTelemetry?.log({
|
|
7085
|
+
name: "provider.redirect.resumed",
|
|
7086
|
+
stage: "redirect_resume",
|
|
7087
|
+
provider: "paypal",
|
|
7088
|
+
paymentMethodCategory: "paypal"
|
|
7089
|
+
});
|
|
7090
|
+
resumeTelemetry?.log({
|
|
7091
|
+
name: "operation.recovery.started",
|
|
7092
|
+
stage: "recovery",
|
|
7093
|
+
provider: "paypal",
|
|
7094
|
+
paymentMethodCategory: "paypal"
|
|
6476
7095
|
});
|
|
6477
7096
|
const paypalStripe = (resumePaypalFlopay ?? resumeFlopay)?.getRawProvider();
|
|
6478
7097
|
if (!paypalStripe) {
|
|
@@ -6502,7 +7121,7 @@ function FloPayCheckout({
|
|
|
6502
7121
|
const paymentMethodId = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
|
|
6503
7122
|
let finalResultStatus = resultStatus;
|
|
6504
7123
|
if (resumeState.sessionId) {
|
|
6505
|
-
const resumeApi = new import_js4.PaymentAPI(resolvedBillingUrl);
|
|
7124
|
+
const resumeApi = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
|
|
6506
7125
|
const resumeSessionResult = await resumeApi.getUnifiedCheckoutSession(resumeState.sessionId);
|
|
6507
7126
|
const resumeSession = resumeSessionResult.data.session;
|
|
6508
7127
|
if (resumeSession && resumeSession.status !== "complete") {
|
|
@@ -6510,6 +7129,7 @@ function FloPayCheckout({
|
|
|
6510
7129
|
billingApiUrl: resolvedBillingUrl,
|
|
6511
7130
|
sessionId: resumeState.sessionId,
|
|
6512
7131
|
session: resumeSession,
|
|
7132
|
+
telemetry: false,
|
|
6513
7133
|
tokenizedData: {
|
|
6514
7134
|
id: paymentMethodId ?? paymentIntent.id,
|
|
6515
7135
|
type: "card",
|
|
@@ -6527,20 +7147,84 @@ function FloPayCheckout({
|
|
|
6527
7147
|
}
|
|
6528
7148
|
}
|
|
6529
7149
|
if (resumeState.sessionId) markSessionRecentlyCompleted(resumeState.sessionId);
|
|
7150
|
+
resumeTelemetry?.log({
|
|
7151
|
+
name: "operation.recovery.completed",
|
|
7152
|
+
stage: "recovery",
|
|
7153
|
+
provider: "paypal",
|
|
7154
|
+
paymentMethodCategory: "paypal"
|
|
7155
|
+
});
|
|
7156
|
+
resumeTelemetry?.performance({
|
|
7157
|
+
stage: "redirect_resume",
|
|
7158
|
+
durationMs: resumeTelemetry.elapsed(redirectResumeStartedAt),
|
|
7159
|
+
durationMode: "machine",
|
|
7160
|
+
provider: "paypal",
|
|
7161
|
+
paymentMethodCategory: "paypal"
|
|
7162
|
+
});
|
|
7163
|
+
resumeTelemetry?.terminal({
|
|
7164
|
+
outcome: "payment_succeeded",
|
|
7165
|
+
provider: "paypal",
|
|
7166
|
+
paymentMethodCategory: "paypal"
|
|
7167
|
+
});
|
|
6530
7168
|
setModeOverlayStatus("success");
|
|
6531
7169
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
6532
|
-
onCompleteRef.current?.({
|
|
7170
|
+
invokeMerchantCallback(() => onCompleteRef.current?.({
|
|
6533
7171
|
status: finalResultStatus,
|
|
6534
7172
|
paymentIntentId: paymentIntent.id,
|
|
6535
7173
|
paymentMethodId,
|
|
6536
7174
|
checkoutMethod: "paypal"
|
|
6537
|
-
});
|
|
7175
|
+
}));
|
|
6538
7176
|
} catch (err) {
|
|
6539
7177
|
const floPayErr = normalizeSavedPaymentError(err);
|
|
6540
7178
|
const method = floPayErr.checkoutMethod ?? "paypal";
|
|
7179
|
+
const expectedDecline = Boolean(
|
|
7180
|
+
floPayErr.declineCode || floPayErr.code?.toLowerCase().includes("declin")
|
|
7181
|
+
);
|
|
7182
|
+
if (resumeTelemetry) {
|
|
7183
|
+
resumeTelemetry.performance({
|
|
7184
|
+
stage: "redirect_resume",
|
|
7185
|
+
durationMs: resumeTelemetry.elapsed(redirectResumeStartedAt),
|
|
7186
|
+
durationMode: "machine",
|
|
7187
|
+
provider: "paypal",
|
|
7188
|
+
paymentMethodCategory: "paypal"
|
|
7189
|
+
});
|
|
7190
|
+
if (expectedDecline) {
|
|
7191
|
+
resumeTelemetry.terminal({
|
|
7192
|
+
outcome: "payment_declined",
|
|
7193
|
+
provider: "paypal",
|
|
7194
|
+
paymentMethodCategory: "paypal"
|
|
7195
|
+
});
|
|
7196
|
+
} else {
|
|
7197
|
+
resumeTelemetry.error({
|
|
7198
|
+
errorCode: "REDIRECT_RESUME_FAILED",
|
|
7199
|
+
stage: "redirect_resume",
|
|
7200
|
+
provider: "paypal",
|
|
7201
|
+
paymentMethodCategory: "paypal"
|
|
7202
|
+
});
|
|
7203
|
+
}
|
|
7204
|
+
} else if (expectedDecline) {
|
|
7205
|
+
const reporter = createStandaloneTelemetryReporter(
|
|
7206
|
+
resolvedBillingUrl,
|
|
7207
|
+
telemetry,
|
|
7208
|
+
telemetryCheckoutContext
|
|
7209
|
+
);
|
|
7210
|
+
reporter.terminal({
|
|
7211
|
+
outcome: "payment_declined",
|
|
7212
|
+
provider: "paypal",
|
|
7213
|
+
paymentMethodCategory: "paypal"
|
|
7214
|
+
});
|
|
7215
|
+
finishStandaloneTelemetry(reporter);
|
|
7216
|
+
} else {
|
|
7217
|
+
reportStandaloneTelemetryError(
|
|
7218
|
+
resolvedBillingUrl,
|
|
7219
|
+
telemetry,
|
|
7220
|
+
telemetryCheckoutContext,
|
|
7221
|
+
"REDIRECT_RESUME_FAILED",
|
|
7222
|
+
"redirect_resume"
|
|
7223
|
+
);
|
|
7224
|
+
}
|
|
6541
7225
|
setModeError(floPayErr.message);
|
|
6542
7226
|
setModeOverlayError(floPayErr.message);
|
|
6543
|
-
onErrorRef.current?.(floPayErr);
|
|
7227
|
+
invokeMerchantCallback(() => onErrorRef.current?.(floPayErr));
|
|
6544
7228
|
emitDecline(method, floPayErr, {
|
|
6545
7229
|
code: floPayErr.code,
|
|
6546
7230
|
declineCode: floPayErr.declineCode
|
|
@@ -6555,8 +7239,8 @@ function FloPayCheckout({
|
|
|
6555
7239
|
setConfirmProcessing(false);
|
|
6556
7240
|
}
|
|
6557
7241
|
})();
|
|
6558
|
-
}, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
|
|
6559
|
-
const initializedHashRef = (0,
|
|
7242
|
+
}, [emitDecline, invokeMerchantCallback, locale, normalizeSavedPaymentError, resolvedBillingUrl, telemetry]);
|
|
7243
|
+
const initializedHashRef = (0, import_react11.useRef)(null);
|
|
6560
7244
|
function hashCreateParams(params) {
|
|
6561
7245
|
const key = JSON.stringify({
|
|
6562
7246
|
c: params?.clientId,
|
|
@@ -6589,60 +7273,123 @@ function FloPayCheckout({
|
|
|
6589
7273
|
}
|
|
6590
7274
|
return `flopay_session_${Math.abs(h).toString(36)}`;
|
|
6591
7275
|
}
|
|
6592
|
-
const createSessionHash = (0,
|
|
7276
|
+
const createSessionHash = (0, import_react11.useMemo)(
|
|
6593
7277
|
() => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
|
|
6594
7278
|
[effectiveCreateSession]
|
|
6595
7279
|
);
|
|
6596
|
-
const createSessionParamsRef = (0,
|
|
7280
|
+
const createSessionParamsRef = (0, import_react11.useRef)(effectiveCreateSession);
|
|
6597
7281
|
createSessionParamsRef.current = effectiveCreateSession;
|
|
6598
|
-
(0,
|
|
7282
|
+
(0, import_react11.useEffect)(() => {
|
|
6599
7283
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
6600
7284
|
}, [sessionIdProp]);
|
|
6601
|
-
(0,
|
|
7285
|
+
(0, import_react11.useEffect)(() => {
|
|
6602
7286
|
autoCheckoutAttempted.current = false;
|
|
6603
7287
|
setModeError(initialErrorMessage);
|
|
6604
7288
|
setModeOverlayError(null);
|
|
6605
7289
|
setModeOverlayStatus(null);
|
|
6606
7290
|
}, [createSessionHash, initialErrorMessage, sessionIdProp]);
|
|
6607
7291
|
async function resolveInlineSession(params, cacheKey) {
|
|
6608
|
-
const
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
7292
|
+
const reporter = createStandaloneTelemetryReporter(
|
|
7293
|
+
resolvedBillingUrl,
|
|
7294
|
+
telemetry,
|
|
7295
|
+
telemetryCheckoutContext
|
|
7296
|
+
);
|
|
7297
|
+
const api = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
|
|
7298
|
+
try {
|
|
7299
|
+
const cached = readCachedInlineSession(cacheKey);
|
|
7300
|
+
reporter.log({
|
|
7301
|
+
name: cached ? "operation.cache.hit" : "operation.cache.miss",
|
|
7302
|
+
stage: "session_create",
|
|
7303
|
+
requestCategory: "session_create"
|
|
7304
|
+
});
|
|
7305
|
+
let sid = cached?.sid ?? null;
|
|
7306
|
+
let realResult = null;
|
|
7307
|
+
if (sid) {
|
|
7308
|
+
try {
|
|
7309
|
+
realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
|
|
7310
|
+
const status = realResult.data.session?.status;
|
|
7311
|
+
if (status === "complete") {
|
|
7312
|
+
if (wasSessionRecentlyCompleted(sid)) {
|
|
7313
|
+
return { sid, result: realResult };
|
|
7314
|
+
}
|
|
7315
|
+
clearCachedInlineSession(cacheKey);
|
|
7316
|
+
sid = null;
|
|
7317
|
+
realResult = null;
|
|
6619
7318
|
}
|
|
7319
|
+
} catch {
|
|
7320
|
+
reporter.log({
|
|
7321
|
+
name: "operation.fallback",
|
|
7322
|
+
stage: "session_read",
|
|
7323
|
+
requestCategory: "session_read"
|
|
7324
|
+
});
|
|
6620
7325
|
clearCachedInlineSession(cacheKey);
|
|
6621
7326
|
sid = null;
|
|
6622
|
-
realResult = null;
|
|
6623
7327
|
}
|
|
6624
|
-
} catch {
|
|
6625
|
-
clearCachedInlineSession(cacheKey);
|
|
6626
|
-
sid = null;
|
|
6627
7328
|
}
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
7329
|
+
if (!sid) {
|
|
7330
|
+
const sessionCreateStartedAt = reporter.now();
|
|
7331
|
+
reporter.log({
|
|
7332
|
+
name: "session.create.started",
|
|
7333
|
+
stage: "session_create",
|
|
7334
|
+
requestCategory: "session_create"
|
|
7335
|
+
});
|
|
7336
|
+
const paramsWithAnalytics = {
|
|
7337
|
+
...params,
|
|
7338
|
+
avsCheck: !!enableAVS,
|
|
7339
|
+
avsConfig: typeof enableAVS === "object" ? enableAVS : void 0,
|
|
7340
|
+
checkoutType: "embedded_checkout",
|
|
7341
|
+
checkoutLayout: children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout"
|
|
7342
|
+
};
|
|
7343
|
+
try {
|
|
7344
|
+
realResult = await api.createAndFetchSession(paramsWithAnalytics);
|
|
7345
|
+
reporter.log({
|
|
7346
|
+
name: "session.request.completed",
|
|
7347
|
+
stage: "session_complete",
|
|
7348
|
+
requestCategory: "session_create",
|
|
7349
|
+
statusClass: "2xx"
|
|
7350
|
+
});
|
|
7351
|
+
reporter.performance({
|
|
7352
|
+
stage: "session_create",
|
|
7353
|
+
durationMs: reporter.now() - sessionCreateStartedAt,
|
|
7354
|
+
durationMode: "machine",
|
|
7355
|
+
requestCategory: "session_create",
|
|
7356
|
+
statusClass: "2xx"
|
|
7357
|
+
});
|
|
7358
|
+
} catch (error) {
|
|
7359
|
+
reporter.performance({
|
|
7360
|
+
stage: "session_create",
|
|
7361
|
+
durationMs: reporter.now() - sessionCreateStartedAt,
|
|
7362
|
+
durationMode: "machine",
|
|
7363
|
+
requestCategory: "session_create",
|
|
7364
|
+
statusClass: "network_error"
|
|
7365
|
+
});
|
|
7366
|
+
if (error instanceof import_shared8.FloPayError && error.type === "validation_error") {
|
|
7367
|
+
reporter.terminal({
|
|
7368
|
+
outcome: "validation_rejected",
|
|
7369
|
+
stage: "session_create",
|
|
7370
|
+
paymentMethodCategory: "unknown"
|
|
7371
|
+
});
|
|
7372
|
+
} else {
|
|
7373
|
+
reporter.error({
|
|
7374
|
+
errorCode: "CHECKOUT_SESSION_CREATE_FAILED",
|
|
7375
|
+
stage: "session_create",
|
|
7376
|
+
paymentMethodCategory: "unknown",
|
|
7377
|
+
requestCategory: "session_create"
|
|
7378
|
+
});
|
|
7379
|
+
}
|
|
7380
|
+
throw error;
|
|
7381
|
+
}
|
|
7382
|
+
sid = realResult.data.session?.id ?? "";
|
|
7383
|
+
if (sid) {
|
|
7384
|
+
persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
|
|
7385
|
+
}
|
|
6641
7386
|
}
|
|
7387
|
+
return { sid: sid ?? "", result: realResult };
|
|
7388
|
+
} finally {
|
|
7389
|
+
finishStandaloneTelemetry(reporter);
|
|
6642
7390
|
}
|
|
6643
|
-
return { sid: sid ?? "", result: realResult };
|
|
6644
7391
|
}
|
|
6645
|
-
const bootstrapInlineSession = (0,
|
|
7392
|
+
const bootstrapInlineSession = (0, import_react11.useCallback)(
|
|
6646
7393
|
async (patch) => {
|
|
6647
7394
|
const baseParams = createSessionParamsRef.current;
|
|
6648
7395
|
if (!baseParams) {
|
|
@@ -6686,7 +7433,8 @@ function FloPayCheckout({
|
|
|
6686
7433
|
publishableKey,
|
|
6687
7434
|
paypalPublishableKey,
|
|
6688
7435
|
billingApiUrl: resolvedBillingUrl,
|
|
6689
|
-
locale
|
|
7436
|
+
locale,
|
|
7437
|
+
telemetry
|
|
6690
7438
|
});
|
|
6691
7439
|
flopayRef.current = instance;
|
|
6692
7440
|
setFloPay(instance);
|
|
@@ -6701,9 +7449,9 @@ function FloPayCheckout({
|
|
|
6701
7449
|
}
|
|
6702
7450
|
return resolved;
|
|
6703
7451
|
},
|
|
6704
|
-
[locale, resolvedBillingUrl]
|
|
7452
|
+
[locale, resolvedBillingUrl, telemetry, telemetryCheckoutContext]
|
|
6705
7453
|
);
|
|
6706
|
-
const handleInlineSessionPatch = (0,
|
|
7454
|
+
const handleInlineSessionPatch = (0, import_react11.useCallback)(async (patch) => {
|
|
6707
7455
|
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
|
|
6708
7456
|
return {
|
|
6709
7457
|
sessionId: resolvedSessionId,
|
|
@@ -6726,7 +7474,7 @@ function FloPayCheckout({
|
|
|
6726
7474
|
resolvedSessionId,
|
|
6727
7475
|
session
|
|
6728
7476
|
]);
|
|
6729
|
-
(0,
|
|
7477
|
+
(0, import_react11.useEffect)(() => {
|
|
6730
7478
|
let cancelled = false;
|
|
6731
7479
|
setLoadError(null);
|
|
6732
7480
|
if (createSessionHash) {
|
|
@@ -6780,7 +7528,9 @@ function FloPayCheckout({
|
|
|
6780
7528
|
setModeOverlayStatus("success");
|
|
6781
7529
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
6782
7530
|
if (!cancelled) {
|
|
6783
|
-
|
|
7531
|
+
invokeMerchantCallback(() => {
|
|
7532
|
+
onCompleteRef.current?.({ status: "succeeded" });
|
|
7533
|
+
});
|
|
6784
7534
|
setModeOverlayStatus(null);
|
|
6785
7535
|
setModeOverlayError(null);
|
|
6786
7536
|
}
|
|
@@ -6800,8 +7550,9 @@ function FloPayCheckout({
|
|
|
6800
7550
|
}
|
|
6801
7551
|
setIsLoading(true);
|
|
6802
7552
|
async function init() {
|
|
7553
|
+
let sessionReadCompleted = false;
|
|
6803
7554
|
try {
|
|
6804
|
-
const api = new import_js4.PaymentAPI(resolvedBillingUrl);
|
|
7555
|
+
const api = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
|
|
6805
7556
|
const result = await api.getUnifiedCheckoutSession(activeSessionId, nonceProp);
|
|
6806
7557
|
if (cancelled) return;
|
|
6807
7558
|
setUnified(result);
|
|
@@ -6812,7 +7563,9 @@ function FloPayCheckout({
|
|
|
6812
7563
|
}
|
|
6813
7564
|
if (sess.status === "complete") {
|
|
6814
7565
|
setIsLoading(false);
|
|
6815
|
-
|
|
7566
|
+
invokeMerchantCallback(() => {
|
|
7567
|
+
onSessionCompletedRef.current?.(sess.successUrl ?? "");
|
|
7568
|
+
});
|
|
6816
7569
|
return;
|
|
6817
7570
|
}
|
|
6818
7571
|
if (sess.status === "expired") {
|
|
@@ -6820,6 +7573,7 @@ function FloPayCheckout({
|
|
|
6820
7573
|
code: "checkout_session_expired"
|
|
6821
7574
|
});
|
|
6822
7575
|
}
|
|
7576
|
+
sessionReadCompleted = true;
|
|
6823
7577
|
const effectiveMode = checkoutModeProp ?? sess.checkoutMode ?? "full";
|
|
6824
7578
|
setCurrentMode(effectiveMode);
|
|
6825
7579
|
const hasPayPalRedirectParams = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("payment_intent");
|
|
@@ -6851,6 +7605,23 @@ function FloPayCheckout({
|
|
|
6851
7605
|
if (!cancelled) setIsLoading(false);
|
|
6852
7606
|
} catch (err) {
|
|
6853
7607
|
if (cancelled) return;
|
|
7608
|
+
if (!(err instanceof import_shared8.FloPayError)) {
|
|
7609
|
+
reportStandaloneTelemetryError(
|
|
7610
|
+
resolvedBillingUrl,
|
|
7611
|
+
telemetry,
|
|
7612
|
+
telemetryCheckoutContext,
|
|
7613
|
+
"INTERNAL_SDK_ERROR",
|
|
7614
|
+
"checkout_mount"
|
|
7615
|
+
);
|
|
7616
|
+
} else if (!sessionReadCompleted && !isExpectedExistingSessionError(err)) {
|
|
7617
|
+
reportStandaloneTelemetryError(
|
|
7618
|
+
resolvedBillingUrl,
|
|
7619
|
+
telemetry,
|
|
7620
|
+
telemetryCheckoutContext,
|
|
7621
|
+
"NETWORK_REQUEST_FAILED",
|
|
7622
|
+
"session_read"
|
|
7623
|
+
);
|
|
7624
|
+
}
|
|
6854
7625
|
const floPayErr = err instanceof import_shared8.FloPayError ? err : new import_shared8.FloPayError(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
|
|
6855
7626
|
setLoadError(floPayErr);
|
|
6856
7627
|
setIsLoading(false);
|
|
@@ -6872,7 +7643,8 @@ function FloPayCheckout({
|
|
|
6872
7643
|
publishableKey,
|
|
6873
7644
|
paypalPublishableKey,
|
|
6874
7645
|
billingApiUrl: resolvedBillingUrl,
|
|
6875
|
-
locale
|
|
7646
|
+
locale,
|
|
7647
|
+
telemetry
|
|
6876
7648
|
});
|
|
6877
7649
|
flopayRef.current = instance;
|
|
6878
7650
|
setFloPay(instance);
|
|
@@ -6889,10 +7661,11 @@ function FloPayCheckout({
|
|
|
6889
7661
|
createSessionHash,
|
|
6890
7662
|
effectiveCreateSessionMode,
|
|
6891
7663
|
initSessionDependency,
|
|
7664
|
+
invokeMerchantCallback,
|
|
6892
7665
|
nonceProp,
|
|
6893
7666
|
runSavedPaymentFlow
|
|
6894
7667
|
]);
|
|
6895
|
-
const handleConfirmCheckout = (0,
|
|
7668
|
+
const handleConfirmCheckout = (0, import_react11.useCallback)(async () => {
|
|
6896
7669
|
if (confirmProcessing || !session) return;
|
|
6897
7670
|
setConfirmProcessing(true);
|
|
6898
7671
|
setModeError(null);
|
|
@@ -6907,7 +7680,7 @@ function FloPayCheckout({
|
|
|
6907
7680
|
}, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
|
|
6908
7681
|
const directPaypalConfig = resolveDirectPaypalConfig(unified);
|
|
6909
7682
|
const isPaypalOnlySession = isPayPalOnlyUnified(unified);
|
|
6910
|
-
const providerOptions = (0,
|
|
7683
|
+
const providerOptions = (0, import_react11.useMemo)(() => {
|
|
6911
7684
|
if (!unified || !session || !unified.data.stripe?.publishableKey) return void 0;
|
|
6912
7685
|
const opts = {
|
|
6913
7686
|
appearance,
|
|
@@ -6926,7 +7699,7 @@ function FloPayCheckout({
|
|
|
6926
7699
|
const shouldHandleInlineSessionPatch = Boolean(
|
|
6927
7700
|
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
|
|
6928
7701
|
);
|
|
6929
|
-
const checkoutValue = (0,
|
|
7702
|
+
const checkoutValue = (0, import_react11.useMemo)(
|
|
6930
7703
|
() => ({
|
|
6931
7704
|
session,
|
|
6932
7705
|
loading: isLoading,
|
|
@@ -6948,7 +7721,7 @@ function FloPayCheckout({
|
|
|
6948
7721
|
]
|
|
6949
7722
|
);
|
|
6950
7723
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
|
|
6951
|
-
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0,
|
|
7724
|
+
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
6952
7725
|
ProcessingOverlay,
|
|
6953
7726
|
{
|
|
6954
7727
|
status: modeOverlayStatus,
|
|
@@ -6957,32 +7730,32 @@ function FloPayCheckout({
|
|
|
6957
7730
|
) : null;
|
|
6958
7731
|
if (isLoading) {
|
|
6959
7732
|
if (loadingNode) {
|
|
6960
|
-
return /* @__PURE__ */ (0,
|
|
7733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
6961
7734
|
loadingNode,
|
|
6962
7735
|
modeOverlay
|
|
6963
7736
|
] });
|
|
6964
7737
|
}
|
|
6965
7738
|
if (layout === "buttons") {
|
|
6966
7739
|
const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
6967
|
-
const skeletonBar = (h) => /* @__PURE__ */ (0,
|
|
7740
|
+
const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
6968
7741
|
height: h,
|
|
6969
7742
|
borderRadius: bundleRadius,
|
|
6970
7743
|
background: "#e5e7eb",
|
|
6971
7744
|
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
6972
7745
|
} });
|
|
6973
|
-
return /* @__PURE__ */ (0,
|
|
6974
|
-
/* @__PURE__ */ (0,
|
|
7746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7747
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
6975
7748
|
showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6976
7749
|
showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6977
7750
|
showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6978
|
-
/* @__PURE__ */ (0,
|
|
7751
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
6979
7752
|
] }),
|
|
6980
7753
|
modeOverlay
|
|
6981
7754
|
] });
|
|
6982
7755
|
}
|
|
6983
|
-
return /* @__PURE__ */ (0,
|
|
6984
|
-
/* @__PURE__ */ (0,
|
|
6985
|
-
/* @__PURE__ */ (0,
|
|
7756
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7757
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
7758
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
6986
7759
|
width: 24,
|
|
6987
7760
|
height: 24,
|
|
6988
7761
|
border: "2px solid #e5e7eb",
|
|
@@ -6990,16 +7763,16 @@ function FloPayCheckout({
|
|
|
6990
7763
|
borderRadius: "50%",
|
|
6991
7764
|
animation: "spin 0.6s linear infinite"
|
|
6992
7765
|
} }),
|
|
6993
|
-
/* @__PURE__ */ (0,
|
|
7766
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
6994
7767
|
] }),
|
|
6995
7768
|
modeOverlay
|
|
6996
7769
|
] });
|
|
6997
7770
|
}
|
|
6998
7771
|
if (loadError) {
|
|
6999
7772
|
if (errorNode) {
|
|
7000
|
-
return /* @__PURE__ */ (0,
|
|
7773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
|
|
7001
7774
|
}
|
|
7002
|
-
return /* @__PURE__ */ (0,
|
|
7775
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7003
7776
|
"div",
|
|
7004
7777
|
{
|
|
7005
7778
|
role: "alert",
|
|
@@ -7015,8 +7788,8 @@ function FloPayCheckout({
|
|
|
7015
7788
|
) });
|
|
7016
7789
|
}
|
|
7017
7790
|
if (shouldShowInterimButtons) {
|
|
7018
|
-
return /* @__PURE__ */ (0,
|
|
7019
|
-
/* @__PURE__ */ (0,
|
|
7791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7792
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7020
7793
|
InterimButtonsView,
|
|
7021
7794
|
{
|
|
7022
7795
|
onButtonClick,
|
|
@@ -7036,27 +7809,11 @@ function FloPayCheckout({
|
|
|
7036
7809
|
] });
|
|
7037
7810
|
}
|
|
7038
7811
|
if (isPaypalOnlySession && session && directPaypalConfig) {
|
|
7039
|
-
return /* @__PURE__ */ (0,
|
|
7040
|
-
/* @__PURE__ */ (0,
|
|
7041
|
-
modeError && /* @__PURE__ */ (0,
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
role: "alert",
|
|
7045
|
-
"data-testid": "flopay-error",
|
|
7046
|
-
style: {
|
|
7047
|
-
padding: "0.625rem 0.875rem",
|
|
7048
|
-
background: "#FEF2F2",
|
|
7049
|
-
border: "1px solid #FECACA",
|
|
7050
|
-
borderRadius: "8px",
|
|
7051
|
-
color: "#991B1B",
|
|
7052
|
-
fontSize: "0.85rem",
|
|
7053
|
-
fontWeight: 600
|
|
7054
|
-
},
|
|
7055
|
-
children: modeError
|
|
7056
|
-
}
|
|
7057
|
-
),
|
|
7058
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
7059
|
-
DirectPayPalButton,
|
|
7812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7813
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
7814
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorBanner, { icon: false, children: modeError }),
|
|
7815
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7816
|
+
InstrumentedDirectPayPalButton,
|
|
7060
7817
|
{
|
|
7061
7818
|
sessionId: activeSessionId,
|
|
7062
7819
|
nonce: session.clientSecret || void 0,
|
|
@@ -7071,6 +7828,8 @@ function FloPayCheckout({
|
|
|
7071
7828
|
onDecline,
|
|
7072
7829
|
onButtonClick,
|
|
7073
7830
|
session,
|
|
7831
|
+
telemetry,
|
|
7832
|
+
telemetryContext: telemetryCheckoutContext,
|
|
7074
7833
|
debug
|
|
7075
7834
|
}
|
|
7076
7835
|
)
|
|
@@ -7079,12 +7838,12 @@ function FloPayCheckout({
|
|
|
7079
7838
|
] });
|
|
7080
7839
|
}
|
|
7081
7840
|
if (!flopay || !providerOptions) {
|
|
7082
|
-
return /* @__PURE__ */ (0,
|
|
7841
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: modeOverlay });
|
|
7083
7842
|
}
|
|
7084
7843
|
if (currentMode === "confirm") {
|
|
7085
|
-
return /* @__PURE__ */ (0,
|
|
7086
|
-
/* @__PURE__ */ (0,
|
|
7087
|
-
modeError && /* @__PURE__ */ (0,
|
|
7844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7845
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className, children: [
|
|
7846
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7088
7847
|
"div",
|
|
7089
7848
|
{
|
|
7090
7849
|
style: {
|
|
@@ -7099,7 +7858,7 @@ function FloPayCheckout({
|
|
|
7099
7858
|
renderConfirmButton ? renderConfirmButton({
|
|
7100
7859
|
onConfirm: handleConfirmCheckout,
|
|
7101
7860
|
isProcessing: confirmProcessing
|
|
7102
|
-
}) : /* @__PURE__ */ (0,
|
|
7861
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7103
7862
|
"button",
|
|
7104
7863
|
{
|
|
7105
7864
|
type: "button",
|
|
@@ -7124,9 +7883,9 @@ function FloPayCheckout({
|
|
|
7124
7883
|
modeOverlay
|
|
7125
7884
|
] });
|
|
7126
7885
|
}
|
|
7127
|
-
return /* @__PURE__ */ (0,
|
|
7128
|
-
/* @__PURE__ */ (0,
|
|
7129
|
-
modeError && /* @__PURE__ */ (0,
|
|
7886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7887
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
7888
|
+
modeError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7130
7889
|
"div",
|
|
7131
7890
|
{
|
|
7132
7891
|
style: {
|
|
@@ -7141,7 +7900,7 @@ function FloPayCheckout({
|
|
|
7141
7900
|
children: modeError
|
|
7142
7901
|
}
|
|
7143
7902
|
),
|
|
7144
|
-
/* @__PURE__ */ (0,
|
|
7903
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7145
7904
|
SessionInjector,
|
|
7146
7905
|
{
|
|
7147
7906
|
sessionId: activeSessionId,
|
|
@@ -7151,7 +7910,7 @@ function FloPayCheckout({
|
|
|
7151
7910
|
children
|
|
7152
7911
|
}
|
|
7153
7912
|
)
|
|
7154
|
-
] }) : /* @__PURE__ */ (0,
|
|
7913
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7155
7914
|
SplitCardForm,
|
|
7156
7915
|
{
|
|
7157
7916
|
sessionId: activeSessionId,
|
|
@@ -7214,8 +7973,8 @@ function SessionInjector({
|
|
|
7214
7973
|
session,
|
|
7215
7974
|
children
|
|
7216
7975
|
}) {
|
|
7217
|
-
return /* @__PURE__ */ (0,
|
|
7218
|
-
if (!
|
|
7976
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: import_react11.default.Children.map(children, (child) => {
|
|
7977
|
+
if (!import_react11.default.isValidElement(child)) return child;
|
|
7219
7978
|
const existing = child.props;
|
|
7220
7979
|
const injected = {};
|
|
7221
7980
|
if (!existing.sessionId) injected.sessionId = sessionId;
|
|
@@ -7230,15 +7989,11 @@ function SessionInjector({
|
|
|
7230
7989
|
injected.lastName = session.customer.lastName;
|
|
7231
7990
|
}
|
|
7232
7991
|
if (Object.keys(injected).length === 0) return child;
|
|
7233
|
-
return
|
|
7992
|
+
return import_react11.default.cloneElement(child, injected);
|
|
7234
7993
|
}) });
|
|
7235
7994
|
}
|
|
7236
7995
|
function InterimButtonsView({
|
|
7237
7996
|
onButtonClick,
|
|
7238
|
-
onCardButtonClick,
|
|
7239
|
-
cardLoading = false,
|
|
7240
|
-
cardOpen,
|
|
7241
|
-
errorMessage,
|
|
7242
7997
|
showPayPal,
|
|
7243
7998
|
showStripe = true,
|
|
7244
7999
|
showApplePay,
|
|
@@ -7250,15 +8005,9 @@ function InterimButtonsView({
|
|
|
7250
8005
|
cardBackButtonContent,
|
|
7251
8006
|
cardTitleContent
|
|
7252
8007
|
}) {
|
|
7253
|
-
const [showCardForm, setShowCardForm] = (0,
|
|
7254
|
-
const
|
|
7255
|
-
(0,
|
|
7256
|
-
if (isCardOpenControlled) {
|
|
7257
|
-
setShowCardForm(cardOpen);
|
|
7258
|
-
}
|
|
7259
|
-
}, [cardOpen, isCardOpenControlled]);
|
|
7260
|
-
const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
|
|
7261
|
-
const bStyles = (0, import_react10.useMemo)(() => {
|
|
8008
|
+
const [showCardForm, setShowCardForm] = (0, import_react11.useState)(false);
|
|
8009
|
+
const themeBundle = (0, import_react11.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
|
|
8010
|
+
const bStyles = (0, import_react11.useMemo)(() => {
|
|
7262
8011
|
const base = themeBundle?.buttonsLayout ?? (0, import_shared8.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
7263
8012
|
if (!stylesOverride) return base;
|
|
7264
8013
|
return {
|
|
@@ -7273,7 +8022,7 @@ function InterimButtonsView({
|
|
|
7273
8022
|
};
|
|
7274
8023
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
7275
8024
|
const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
7276
|
-
const skeleton = (h) => /* @__PURE__ */ (0,
|
|
8025
|
+
const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
7277
8026
|
height: h,
|
|
7278
8027
|
borderRadius: skeletonRadius,
|
|
7279
8028
|
background: "#e5e7eb",
|
|
@@ -7285,25 +8034,20 @@ function InterimButtonsView({
|
|
|
7285
8034
|
const inputBg = bStyles.cardInputBackground ?? "white";
|
|
7286
8035
|
const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
|
|
7287
8036
|
const hideTitle = isEmptySlotContent(cardTitleContent);
|
|
7288
|
-
return /* @__PURE__ */ (0,
|
|
8037
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: {
|
|
7289
8038
|
backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
|
|
7290
8039
|
borderRadius: "8px",
|
|
7291
8040
|
animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
|
|
7292
8041
|
overflow: "hidden",
|
|
7293
8042
|
...bStyles.cardFormContainer
|
|
7294
8043
|
}, children: [
|
|
7295
|
-
/* @__PURE__ */ (0,
|
|
7296
|
-
/* @__PURE__ */ (0,
|
|
8044
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
|
|
8045
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
7297
8046
|
"button",
|
|
7298
8047
|
{
|
|
7299
8048
|
type: "button",
|
|
7300
|
-
onClick: () =>
|
|
7301
|
-
if (!isCardOpenControlled) {
|
|
7302
|
-
setShowCardForm(false);
|
|
7303
|
-
}
|
|
7304
|
-
},
|
|
8049
|
+
onClick: () => setShowCardForm(false),
|
|
7305
8050
|
"aria-label": "Back to payment methods",
|
|
7306
|
-
disabled: isCardOpenControlled || cardLoading,
|
|
7307
8051
|
style: {
|
|
7308
8052
|
display: "inline-flex",
|
|
7309
8053
|
alignItems: "center",
|
|
@@ -7315,12 +8059,12 @@ function InterimButtonsView({
|
|
|
7315
8059
|
fontWeight: 500,
|
|
7316
8060
|
padding: 0,
|
|
7317
8061
|
flexShrink: 0,
|
|
7318
|
-
opacity:
|
|
7319
|
-
cursor:
|
|
8062
|
+
opacity: 1,
|
|
8063
|
+
cursor: "pointer",
|
|
7320
8064
|
...bStyles.backButton
|
|
7321
8065
|
},
|
|
7322
8066
|
children: [
|
|
7323
|
-
/* @__PURE__ */ (0,
|
|
8067
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: {
|
|
7324
8068
|
display: "inline-flex",
|
|
7325
8069
|
alignItems: "center",
|
|
7326
8070
|
justifyContent: "center",
|
|
@@ -7329,12 +8073,12 @@ function InterimButtonsView({
|
|
|
7329
8073
|
borderRadius: "50%",
|
|
7330
8074
|
backgroundColor: "#f3f4f6",
|
|
7331
8075
|
...bStyles.backButtonIcon
|
|
7332
|
-
}, children: /* @__PURE__ */ (0,
|
|
7333
|
-
/* @__PURE__ */ (0,
|
|
8076
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime9.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_runtime9.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
8077
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
7334
8078
|
]
|
|
7335
8079
|
}
|
|
7336
8080
|
),
|
|
7337
|
-
hideTitle ? /* @__PURE__ */ (0,
|
|
8081
|
+
hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
7338
8082
|
flex: 1,
|
|
7339
8083
|
textAlign: "center",
|
|
7340
8084
|
fontWeight: 600,
|
|
@@ -7342,11 +8086,11 @@ function InterimButtonsView({
|
|
|
7342
8086
|
color: "#262833",
|
|
7343
8087
|
paddingRight: 80,
|
|
7344
8088
|
...bStyles.title
|
|
7345
|
-
}, children: /* @__PURE__ */ (0,
|
|
8089
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TitleContentSlot, { content: cardTitleContent }) })
|
|
7346
8090
|
] }),
|
|
7347
|
-
/* @__PURE__ */ (0,
|
|
7348
|
-
/* @__PURE__ */ (0,
|
|
7349
|
-
/* @__PURE__ */ (0,
|
|
8091
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
8092
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex" }, children: [
|
|
8093
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
7350
8094
|
flex: 1,
|
|
7351
8095
|
backgroundColor: inputBg,
|
|
7352
8096
|
borderTop: "none",
|
|
@@ -7356,8 +8100,8 @@ function InterimButtonsView({
|
|
|
7356
8100
|
borderBottomLeftRadius: 8,
|
|
7357
8101
|
padding: 12,
|
|
7358
8102
|
height: 45
|
|
7359
|
-
}, children: /* @__PURE__ */ (0,
|
|
7360
|
-
/* @__PURE__ */ (0,
|
|
8103
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
8104
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
7361
8105
|
flex: 1,
|
|
7362
8106
|
backgroundColor: inputBg,
|
|
7363
8107
|
borderTop: "none",
|
|
@@ -7367,10 +8111,10 @@ function InterimButtonsView({
|
|
|
7367
8111
|
borderBottomRightRadius: 8,
|
|
7368
8112
|
padding: 12,
|
|
7369
8113
|
height: 45
|
|
7370
|
-
}, children: /* @__PURE__ */ (0,
|
|
8114
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
7371
8115
|
] }),
|
|
7372
|
-
/* @__PURE__ */ (0,
|
|
7373
|
-
/* @__PURE__ */ (0,
|
|
8116
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
8117
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
7374
8118
|
height: 50,
|
|
7375
8119
|
borderRadius: 8,
|
|
7376
8120
|
marginTop: 16,
|
|
@@ -7379,7 +8123,7 @@ function InterimButtonsView({
|
|
|
7379
8123
|
...bStyles.submitButton,
|
|
7380
8124
|
opacity: 0.5
|
|
7381
8125
|
} }),
|
|
7382
|
-
/* @__PURE__ */ (0,
|
|
8126
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
|
|
7383
8127
|
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
7384
8128
|
@keyframes flopay-interim-expand {
|
|
7385
8129
|
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
@@ -7389,23 +8133,17 @@ function InterimButtonsView({
|
|
|
7389
8133
|
` })
|
|
7390
8134
|
] });
|
|
7391
8135
|
}
|
|
7392
|
-
return /* @__PURE__ */ (0,
|
|
8136
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
7393
8137
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
7394
8138
|
showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
7395
|
-
showStripe && /* @__PURE__ */ (0,
|
|
8139
|
+
showStripe && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7396
8140
|
"button",
|
|
7397
8141
|
{
|
|
7398
8142
|
type: "button",
|
|
7399
|
-
onClick:
|
|
7400
|
-
if (cardLoading) return;
|
|
7401
|
-
if (onCardButtonClick) {
|
|
7402
|
-
await onCardButtonClick();
|
|
7403
|
-
return;
|
|
7404
|
-
}
|
|
8143
|
+
onClick: () => {
|
|
7405
8144
|
onButtonClick?.("card");
|
|
7406
8145
|
setShowCardForm(true);
|
|
7407
8146
|
},
|
|
7408
|
-
disabled: cardLoading,
|
|
7409
8147
|
style: {
|
|
7410
8148
|
width: "100%",
|
|
7411
8149
|
...cardButtonSizing,
|
|
@@ -7415,7 +8153,7 @@ function InterimButtonsView({
|
|
|
7415
8153
|
borderRadius: "8px",
|
|
7416
8154
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
7417
8155
|
fontWeight: 600,
|
|
7418
|
-
cursor:
|
|
8156
|
+
cursor: "pointer",
|
|
7419
8157
|
display: "flex",
|
|
7420
8158
|
alignItems: "center",
|
|
7421
8159
|
justifyContent: "center",
|
|
@@ -7423,7 +8161,7 @@ function InterimButtonsView({
|
|
|
7423
8161
|
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
7424
8162
|
transition: "transform 0.1s",
|
|
7425
8163
|
position: "relative",
|
|
7426
|
-
opacity:
|
|
8164
|
+
opacity: 1,
|
|
7427
8165
|
...bStyles.cardButton
|
|
7428
8166
|
},
|
|
7429
8167
|
onMouseDown: (e) => {
|
|
@@ -7432,39 +8170,22 @@ function InterimButtonsView({
|
|
|
7432
8170
|
onMouseUp: (e) => {
|
|
7433
8171
|
e.currentTarget.style.transform = "scale(1)";
|
|
7434
8172
|
},
|
|
7435
|
-
children: /* @__PURE__ */ (0,
|
|
8173
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CardButtonContentSlot, { content: cardButtonContent })
|
|
7436
8174
|
}
|
|
7437
8175
|
),
|
|
7438
|
-
|
|
7439
|
-
margin: "0.25rem 0",
|
|
7440
|
-
padding: "0.625rem 0.875rem",
|
|
7441
|
-
background: "#FEF2F2",
|
|
7442
|
-
border: "1px solid #FECACA",
|
|
7443
|
-
borderRadius: "8px",
|
|
7444
|
-
color: "#991B1B",
|
|
7445
|
-
fontSize: "0.85rem",
|
|
7446
|
-
fontWeight: 600,
|
|
7447
|
-
display: "flex",
|
|
7448
|
-
alignItems: "center",
|
|
7449
|
-
gap: "0.5rem",
|
|
7450
|
-
...bStyles.errorBanner
|
|
7451
|
-
}, children: [
|
|
7452
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
7453
|
-
errorMessage
|
|
7454
|
-
] }),
|
|
7455
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
8176
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
7456
8177
|
] });
|
|
7457
8178
|
}
|
|
7458
8179
|
|
|
7459
8180
|
// src/checkout-form.tsx
|
|
7460
8181
|
var import_js5 = require("@flopay/js");
|
|
7461
8182
|
var import_shared9 = require("@flopay/shared");
|
|
7462
|
-
var
|
|
7463
|
-
var
|
|
8183
|
+
var import_react12 = require("react");
|
|
8184
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
7464
8185
|
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
7465
|
-
var CheckoutForm = (0,
|
|
8186
|
+
var CheckoutForm = (0, import_react12.forwardRef)(
|
|
7466
8187
|
function CheckoutForm2(props, ref) {
|
|
7467
|
-
return /* @__PURE__ */ (0,
|
|
8188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
|
|
7468
8189
|
}
|
|
7469
8190
|
);
|
|
7470
8191
|
function CheckoutFormInner({
|
|
@@ -7494,27 +8215,27 @@ function CheckoutFormInner({
|
|
|
7494
8215
|
const paypalFlopay = usePayPalFloPay();
|
|
7495
8216
|
const elements = useElements();
|
|
7496
8217
|
const contextBillingUrl = useBillingApiUrl();
|
|
7497
|
-
const [processing, setProcessing] = (0,
|
|
7498
|
-
const [error, setError] = (0,
|
|
7499
|
-
const [is3DSActive, setIs3DSActive] = (0,
|
|
8218
|
+
const [processing, setProcessing] = (0, import_react12.useState)(false);
|
|
8219
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
8220
|
+
const [is3DSActive, setIs3DSActive] = (0, import_react12.useState)(false);
|
|
7500
8221
|
const displayError = externalError ?? error;
|
|
7501
8222
|
const isSubmitting = externalProcessing ?? processing;
|
|
7502
8223
|
const isSelfContained = !onTokenizedBody;
|
|
7503
8224
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
7504
|
-
const updateError = (0,
|
|
8225
|
+
const updateError = (0, import_react12.useCallback)(
|
|
7505
8226
|
(err) => {
|
|
7506
8227
|
setError(err);
|
|
7507
8228
|
onErrorChange?.(err);
|
|
7508
8229
|
},
|
|
7509
8230
|
[onErrorChange]
|
|
7510
8231
|
);
|
|
7511
|
-
const emitDecline = (0,
|
|
8232
|
+
const emitDecline = (0, import_react12.useCallback)(
|
|
7512
8233
|
(input, overrides) => {
|
|
7513
8234
|
onDecline?.(buildDeclineEvent("card", input, overrides));
|
|
7514
8235
|
},
|
|
7515
8236
|
[onDecline]
|
|
7516
8237
|
);
|
|
7517
|
-
const processPaymentInternal = (0,
|
|
8238
|
+
const processPaymentInternal = (0, import_react12.useCallback)(
|
|
7518
8239
|
async (tokenizedBody, completionPaymentMethodId) => {
|
|
7519
8240
|
setProcessing(true);
|
|
7520
8241
|
updateError(null);
|
|
@@ -7626,7 +8347,7 @@ function CheckoutFormInner({
|
|
|
7626
8347
|
},
|
|
7627
8348
|
[baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
|
|
7628
8349
|
);
|
|
7629
|
-
const dispatchTokenizedBody = (0,
|
|
8350
|
+
const dispatchTokenizedBody = (0, import_react12.useCallback)(
|
|
7630
8351
|
(tokenizedBody) => {
|
|
7631
8352
|
if (onTokenizedBody) {
|
|
7632
8353
|
onTokenizedBody(tokenizedBody);
|
|
@@ -7636,7 +8357,7 @@ function CheckoutFormInner({
|
|
|
7636
8357
|
},
|
|
7637
8358
|
[onTokenizedBody, processPaymentInternal]
|
|
7638
8359
|
);
|
|
7639
|
-
(0,
|
|
8360
|
+
(0, import_react12.useImperativeHandle)(innerRef, () => ({
|
|
7640
8361
|
async handleNextAction(secret) {
|
|
7641
8362
|
if (!flopay) return;
|
|
7642
8363
|
setIs3DSActive(true);
|
|
@@ -7663,7 +8384,7 @@ function CheckoutFormInner({
|
|
|
7663
8384
|
}
|
|
7664
8385
|
}
|
|
7665
8386
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
7666
|
-
(0,
|
|
8387
|
+
(0, import_react12.useEffect)(() => {
|
|
7667
8388
|
if (typeof window === "undefined") return;
|
|
7668
8389
|
const stored = localStorage.getItem(WALLET_RESUME_KEY);
|
|
7669
8390
|
if (!stored) return;
|
|
@@ -7681,7 +8402,7 @@ function CheckoutFormInner({
|
|
|
7681
8402
|
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
7682
8403
|
}
|
|
7683
8404
|
}, [sessionId, dispatchTokenizedBody]);
|
|
7684
|
-
const handleSubmit = (0,
|
|
8405
|
+
const handleSubmit = (0, import_react12.useCallback)(
|
|
7685
8406
|
async (e) => {
|
|
7686
8407
|
e.preventDefault();
|
|
7687
8408
|
if (!flopay || !elements || isSubmitting) return;
|
|
@@ -7707,8 +8428,7 @@ function CheckoutFormInner({
|
|
|
7707
8428
|
if (!sessionId || !email) {
|
|
7708
8429
|
throw new import_shared9.FloPayError("Missing sessionId or email", "validation_error");
|
|
7709
8430
|
}
|
|
7710
|
-
const intentHeaders =
|
|
7711
|
-
if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
|
|
8431
|
+
const intentHeaders = intentRequestHeaders(nonce);
|
|
7712
8432
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
7713
8433
|
method: "POST",
|
|
7714
8434
|
headers: intentHeaders,
|
|
@@ -7773,8 +8493,8 @@ function CheckoutFormInner({
|
|
|
7773
8493
|
[flopay, elements, isSubmitting, sessionId, nonce, email, firstName, lastName, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
|
|
7774
8494
|
);
|
|
7775
8495
|
const isReady = flopay !== null && elements !== null;
|
|
7776
|
-
return /* @__PURE__ */ (0,
|
|
7777
|
-
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0,
|
|
8496
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
8497
|
+
(is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": "flopay-overlay", style: {
|
|
7778
8498
|
position: "absolute",
|
|
7779
8499
|
inset: 0,
|
|
7780
8500
|
background: "rgba(255,255,255,0.7)",
|
|
@@ -7783,12 +8503,12 @@ function CheckoutFormInner({
|
|
|
7783
8503
|
justifyContent: "center",
|
|
7784
8504
|
zIndex: 10
|
|
7785
8505
|
}, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
|
|
7786
|
-
!isReady && /* @__PURE__ */ (0,
|
|
7787
|
-
isReady && /* @__PURE__ */ (0,
|
|
7788
|
-
/* @__PURE__ */ (0,
|
|
7789
|
-
showAddress && /* @__PURE__ */ (0,
|
|
7790
|
-
displayError && /* @__PURE__ */ (0,
|
|
7791
|
-
children ?? /* @__PURE__ */ (0,
|
|
8506
|
+
!isReady && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
|
|
8507
|
+
isReady && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
8508
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PaymentElement, { options: { layout } }),
|
|
8509
|
+
showAddress && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
|
|
8510
|
+
displayError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
|
|
8511
|
+
children ?? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
7792
8512
|
"button",
|
|
7793
8513
|
{
|
|
7794
8514
|
type: "submit",
|
|
@@ -7804,8 +8524,8 @@ function CheckoutFormInner({
|
|
|
7804
8524
|
// src/paypal-button.tsx
|
|
7805
8525
|
var import_js6 = require("@flopay/js");
|
|
7806
8526
|
var import_shared10 = require("@flopay/shared");
|
|
7807
|
-
var
|
|
7808
|
-
var
|
|
8527
|
+
var import_react13 = require("react");
|
|
8528
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
7809
8529
|
function PayPalButton({
|
|
7810
8530
|
sessionId,
|
|
7811
8531
|
nonce,
|
|
@@ -7823,11 +8543,11 @@ function PayPalButton({
|
|
|
7823
8543
|
const flopay = useFloPay();
|
|
7824
8544
|
const elements = useElements();
|
|
7825
8545
|
const contextBillingUrl = useBillingApiUrl();
|
|
7826
|
-
const [ready, setReady] = (0,
|
|
7827
|
-
const [submitting, setSubmitting] = (0,
|
|
7828
|
-
const paypalResumeAttempted = (0,
|
|
8546
|
+
const [ready, setReady] = (0, import_react13.useState)(false);
|
|
8547
|
+
const [submitting, setSubmitting] = (0, import_react13.useState)(false);
|
|
8548
|
+
const paypalResumeAttempted = (0, import_react13.useRef)(false);
|
|
7829
8549
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
7830
|
-
const processPaymentInternal = (0,
|
|
8550
|
+
const processPaymentInternal = (0, import_react13.useCallback)(
|
|
7831
8551
|
async (tokenizedBody) => {
|
|
7832
8552
|
try {
|
|
7833
8553
|
const api = new import_js6.PaymentAPI(baseUrl);
|
|
@@ -7855,7 +8575,7 @@ function PayPalButton({
|
|
|
7855
8575
|
},
|
|
7856
8576
|
[baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
|
|
7857
8577
|
);
|
|
7858
|
-
const dispatchTokenizedBody = (0,
|
|
8578
|
+
const dispatchTokenizedBody = (0, import_react13.useCallback)(
|
|
7859
8579
|
(body) => {
|
|
7860
8580
|
if (onTokenizedBody) {
|
|
7861
8581
|
onTokenizedBody(body);
|
|
@@ -7865,7 +8585,7 @@ function PayPalButton({
|
|
|
7865
8585
|
},
|
|
7866
8586
|
[onTokenizedBody, processPaymentInternal]
|
|
7867
8587
|
);
|
|
7868
|
-
(0,
|
|
8588
|
+
(0, import_react13.useEffect)(() => {
|
|
7869
8589
|
if (!flopay || paypalResumeAttempted.current) return;
|
|
7870
8590
|
const params = new URLSearchParams(window.location.search);
|
|
7871
8591
|
const paymentIntentId = params.get("payment_intent");
|
|
@@ -7913,7 +8633,7 @@ function PayPalButton({
|
|
|
7913
8633
|
}
|
|
7914
8634
|
})();
|
|
7915
8635
|
}, [flopay, dispatchTokenizedBody, onErrorChange]);
|
|
7916
|
-
const handlePayPalConfirm = (0,
|
|
8636
|
+
const handlePayPalConfirm = (0, import_react13.useCallback)(async () => {
|
|
7917
8637
|
if (!flopay || !elements) return;
|
|
7918
8638
|
try {
|
|
7919
8639
|
setSubmitting(true);
|
|
@@ -7947,11 +8667,11 @@ function PayPalButton({
|
|
|
7947
8667
|
}
|
|
7948
8668
|
}, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
|
|
7949
8669
|
if (!flopay || !elements) {
|
|
7950
|
-
return /* @__PURE__ */ (0,
|
|
8670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
|
|
7951
8671
|
}
|
|
7952
|
-
return /* @__PURE__ */ (0,
|
|
7953
|
-
!ready && /* @__PURE__ */ (0,
|
|
7954
|
-
/* @__PURE__ */ (0,
|
|
8672
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
8673
|
+
!ready && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
|
|
8674
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7955
8675
|
"button",
|
|
7956
8676
|
{
|
|
7957
8677
|
type: "button",
|
|
@@ -7973,7 +8693,7 @@ function PayPalButton({
|
|
|
7973
8693
|
children: submitting ? "Processing..." : "PayPal"
|
|
7974
8694
|
}
|
|
7975
8695
|
) }),
|
|
7976
|
-
(submitting || isProcessing) && /* @__PURE__ */ (0,
|
|
8696
|
+
(submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: {
|
|
7977
8697
|
position: "fixed",
|
|
7978
8698
|
inset: 0,
|
|
7979
8699
|
background: "rgba(0,0,0,0.4)",
|
|
@@ -7981,7 +8701,7 @@ function PayPalButton({
|
|
|
7981
8701
|
alignItems: "center",
|
|
7982
8702
|
justifyContent: "center",
|
|
7983
8703
|
zIndex: 1e3
|
|
7984
|
-
}, children: /* @__PURE__ */ (0,
|
|
8704
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: {
|
|
7985
8705
|
background: "white",
|
|
7986
8706
|
borderRadius: 8,
|
|
7987
8707
|
padding: "1.5rem",
|
|
@@ -7993,10 +8713,10 @@ function PayPalButton({
|
|
|
7993
8713
|
}
|
|
7994
8714
|
|
|
7995
8715
|
// src/automatic-payment-button.tsx
|
|
7996
|
-
var
|
|
8716
|
+
var import_react14 = require("react");
|
|
7997
8717
|
var import_js7 = require("@flopay/js");
|
|
7998
8718
|
var import_shared11 = require("@flopay/shared");
|
|
7999
|
-
var
|
|
8719
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
8000
8720
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
|
|
8001
8721
|
function sleep2(ms) {
|
|
8002
8722
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -8076,11 +8796,11 @@ function FloPayAutomaticPaymentButton({
|
|
|
8076
8796
|
style,
|
|
8077
8797
|
...buttonProps
|
|
8078
8798
|
}) {
|
|
8079
|
-
const resolvedBillingUrl = (0,
|
|
8799
|
+
const resolvedBillingUrl = (0, import_react14.useMemo)(
|
|
8080
8800
|
() => (0, import_shared11.resolveBillingApiUrl)(billingApiUrl),
|
|
8081
8801
|
[billingApiUrl]
|
|
8082
8802
|
);
|
|
8083
|
-
const createSessionDraft = (0,
|
|
8803
|
+
const createSessionDraft = (0, import_react14.useMemo)(
|
|
8084
8804
|
() => resolveCreateSessionDraft({
|
|
8085
8805
|
createSession,
|
|
8086
8806
|
clientId,
|
|
@@ -8108,37 +8828,37 @@ function FloPayAutomaticPaymentButton({
|
|
|
8108
8828
|
utmMetadata
|
|
8109
8829
|
]
|
|
8110
8830
|
);
|
|
8111
|
-
const [isProcessing, setIsProcessing] = (0,
|
|
8112
|
-
const [overlayStatus, setOverlayStatus] = (0,
|
|
8113
|
-
const [overlayError, setOverlayError] = (0,
|
|
8114
|
-
const [fallbackSession, setFallbackSession] = (0,
|
|
8115
|
-
const isMountedRef = (0,
|
|
8116
|
-
const threeDsAbortRef = (0,
|
|
8117
|
-
const fallbackSessionRef = (0,
|
|
8118
|
-
const onSuccessRef = (0,
|
|
8119
|
-
const onErrorRef = (0,
|
|
8120
|
-
const onDeclineRef = (0,
|
|
8121
|
-
(0,
|
|
8831
|
+
const [isProcessing, setIsProcessing] = (0, import_react14.useState)(false);
|
|
8832
|
+
const [overlayStatus, setOverlayStatus] = (0, import_react14.useState)(null);
|
|
8833
|
+
const [overlayError, setOverlayError] = (0, import_react14.useState)(null);
|
|
8834
|
+
const [fallbackSession, setFallbackSession] = (0, import_react14.useState)(null);
|
|
8835
|
+
const isMountedRef = (0, import_react14.useRef)(true);
|
|
8836
|
+
const threeDsAbortRef = (0, import_react14.useRef)(null);
|
|
8837
|
+
const fallbackSessionRef = (0, import_react14.useRef)(fallbackSession);
|
|
8838
|
+
const onSuccessRef = (0, import_react14.useRef)(onSuccess);
|
|
8839
|
+
const onErrorRef = (0, import_react14.useRef)(onError);
|
|
8840
|
+
const onDeclineRef = (0, import_react14.useRef)(onDecline);
|
|
8841
|
+
(0, import_react14.useEffect)(() => {
|
|
8122
8842
|
fallbackSessionRef.current = fallbackSession;
|
|
8123
8843
|
}, [fallbackSession]);
|
|
8124
|
-
(0,
|
|
8844
|
+
(0, import_react14.useEffect)(() => {
|
|
8125
8845
|
onSuccessRef.current = onSuccess;
|
|
8126
8846
|
}, [onSuccess]);
|
|
8127
|
-
(0,
|
|
8847
|
+
(0, import_react14.useEffect)(() => {
|
|
8128
8848
|
onErrorRef.current = onError;
|
|
8129
8849
|
}, [onError]);
|
|
8130
|
-
(0,
|
|
8850
|
+
(0, import_react14.useEffect)(() => {
|
|
8131
8851
|
onDeclineRef.current = onDecline;
|
|
8132
8852
|
}, [onDecline]);
|
|
8133
|
-
(0,
|
|
8853
|
+
(0, import_react14.useEffect)(() => {
|
|
8134
8854
|
isMountedRef.current = true;
|
|
8135
8855
|
return () => {
|
|
8136
8856
|
isMountedRef.current = false;
|
|
8137
8857
|
threeDsAbortRef.current?.abort();
|
|
8138
8858
|
};
|
|
8139
8859
|
}, []);
|
|
8140
|
-
(0,
|
|
8141
|
-
if (
|
|
8860
|
+
(0, import_react14.useEffect)(() => {
|
|
8861
|
+
if (typeof window === "undefined") {
|
|
8142
8862
|
return;
|
|
8143
8863
|
}
|
|
8144
8864
|
const handleKeyDown = (event) => {
|
|
@@ -8150,14 +8870,14 @@ function FloPayAutomaticPaymentButton({
|
|
|
8150
8870
|
return () => {
|
|
8151
8871
|
window.removeEventListener("keydown", handleKeyDown);
|
|
8152
8872
|
};
|
|
8153
|
-
}, [
|
|
8154
|
-
const emitDecline = (0,
|
|
8873
|
+
}, []);
|
|
8874
|
+
const emitDecline = (0, import_react14.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
|
|
8155
8875
|
onDeclineRef.current?.(buildDeclineEvent(method, error, {
|
|
8156
8876
|
code: error.code,
|
|
8157
8877
|
declineCode: error.declineCode
|
|
8158
8878
|
}));
|
|
8159
8879
|
}, []);
|
|
8160
|
-
const showSuccess = (0,
|
|
8880
|
+
const showSuccess = (0, import_react14.useCallback)(async (event) => {
|
|
8161
8881
|
if (!isMountedRef.current) return;
|
|
8162
8882
|
setOverlayError(null);
|
|
8163
8883
|
setOverlayStatus("success");
|
|
@@ -8165,7 +8885,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8165
8885
|
if (!isMountedRef.current) return;
|
|
8166
8886
|
onSuccessRef.current?.(event);
|
|
8167
8887
|
}, []);
|
|
8168
|
-
const showError = (0,
|
|
8888
|
+
const showError = (0, import_react14.useCallback)(async (error, options) => {
|
|
8169
8889
|
if (!isMountedRef.current) return;
|
|
8170
8890
|
onErrorRef.current?.(error);
|
|
8171
8891
|
if (options?.emitDecline) {
|
|
@@ -8175,7 +8895,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8175
8895
|
setOverlayStatus("error");
|
|
8176
8896
|
await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
|
|
8177
8897
|
}, [emitDecline]);
|
|
8178
|
-
const processResolvedSession = (0,
|
|
8898
|
+
const processResolvedSession = (0, import_react14.useCallback)(async (apiResult, resolvedSessionId, options) => {
|
|
8179
8899
|
const session = apiResult.data.session ?? null;
|
|
8180
8900
|
if (!session) {
|
|
8181
8901
|
throw new import_shared11.FloPayError("No session data returned", "api_error");
|
|
@@ -8331,7 +9051,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8331
9051
|
showError,
|
|
8332
9052
|
showSuccess
|
|
8333
9053
|
]);
|
|
8334
|
-
const handleButtonClick = (0,
|
|
9054
|
+
const handleButtonClick = (0, import_react14.useCallback)(async (event) => {
|
|
8335
9055
|
buttonProps.onClick?.(event);
|
|
8336
9056
|
if (event.defaultPrevented || disabled || isProcessing) {
|
|
8337
9057
|
return;
|
|
@@ -8413,7 +9133,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8413
9133
|
showError,
|
|
8414
9134
|
showSuccess
|
|
8415
9135
|
]);
|
|
8416
|
-
const handleFallbackComplete = (0,
|
|
9136
|
+
const handleFallbackComplete = (0, import_react14.useCallback)((result) => {
|
|
8417
9137
|
const activeFallback = fallbackSessionRef.current;
|
|
8418
9138
|
setFallbackSession(null);
|
|
8419
9139
|
onSuccessRef.current?.({
|
|
@@ -8423,14 +9143,14 @@ function FloPayAutomaticPaymentButton({
|
|
|
8423
9143
|
autoCompleted: false
|
|
8424
9144
|
});
|
|
8425
9145
|
}, []);
|
|
8426
|
-
const handleFallbackError = (0,
|
|
9146
|
+
const handleFallbackError = (0, import_react14.useCallback)((error) => {
|
|
8427
9147
|
onErrorRef.current?.(error);
|
|
8428
9148
|
}, []);
|
|
8429
|
-
const handleFallbackDecline = (0,
|
|
9149
|
+
const handleFallbackDecline = (0, import_react14.useCallback)((decline) => {
|
|
8430
9150
|
onDeclineRef.current?.(decline);
|
|
8431
9151
|
}, []);
|
|
8432
|
-
const themeBundle = (0,
|
|
8433
|
-
const bStyles = (0,
|
|
9152
|
+
const themeBundle = (0, import_react14.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
|
|
9153
|
+
const bStyles = (0, import_react14.useMemo)(() => {
|
|
8434
9154
|
const base = themeBundle?.buttonsLayout ?? (0, import_shared11.resolveButtonsLayoutTheme)(buttonsTheme);
|
|
8435
9155
|
if (!stylesOverride) return base;
|
|
8436
9156
|
return {
|
|
@@ -8439,7 +9159,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8439
9159
|
cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
|
|
8440
9160
|
};
|
|
8441
9161
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
8442
|
-
const resolvedAppearance = (0,
|
|
9162
|
+
const resolvedAppearance = (0, import_react14.useMemo)(() => {
|
|
8443
9163
|
const bundleAppearance = themeBundle?.appearance;
|
|
8444
9164
|
if (!appearance) return bundleAppearance;
|
|
8445
9165
|
if (!bundleAppearance) return appearance;
|
|
@@ -8457,8 +9177,8 @@ function FloPayAutomaticPaymentButton({
|
|
|
8457
9177
|
const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
|
|
8458
9178
|
const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
|
|
8459
9179
|
const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
8460
|
-
return /* @__PURE__ */ (0,
|
|
8461
|
-
/* @__PURE__ */ (0,
|
|
9180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
9181
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
8462
9182
|
"button",
|
|
8463
9183
|
{
|
|
8464
9184
|
...buttonProps,
|
|
@@ -8522,17 +9242,17 @@ function FloPayAutomaticPaymentButton({
|
|
|
8522
9242
|
e.currentTarget.style.transform = "scale(1)";
|
|
8523
9243
|
}
|
|
8524
9244
|
},
|
|
8525
|
-
children: /* @__PURE__ */ (0,
|
|
9245
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardButtonContentSlot, { content: children })
|
|
8526
9246
|
}
|
|
8527
9247
|
),
|
|
8528
|
-
overlayStatus && /* @__PURE__ */ (0,
|
|
9248
|
+
overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
8529
9249
|
ProcessingOverlay,
|
|
8530
9250
|
{
|
|
8531
9251
|
status: overlayStatus,
|
|
8532
9252
|
errorMessage: overlayError
|
|
8533
9253
|
}
|
|
8534
9254
|
),
|
|
8535
|
-
fallbackSession && /* @__PURE__ */ (0,
|
|
9255
|
+
fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
8536
9256
|
"div",
|
|
8537
9257
|
{
|
|
8538
9258
|
"data-testid": "flopay-automatic-payment-fallback",
|
|
@@ -8553,7 +9273,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8553
9273
|
padding: "1.5rem",
|
|
8554
9274
|
zIndex: 1100
|
|
8555
9275
|
},
|
|
8556
|
-
children: /* @__PURE__ */ (0,
|
|
9276
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
8557
9277
|
"div",
|
|
8558
9278
|
{
|
|
8559
9279
|
style: {
|
|
@@ -8569,7 +9289,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8569
9289
|
flexDirection: "column",
|
|
8570
9290
|
gap: "1rem"
|
|
8571
9291
|
},
|
|
8572
|
-
children: /* @__PURE__ */ (0,
|
|
9292
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
8573
9293
|
FloPayCheckout,
|
|
8574
9294
|
{
|
|
8575
9295
|
sessionId: fallbackSession.sessionId,
|