@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.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/provider.tsx
|
|
2
|
-
import { useEffect, useState, useMemo } from "react";
|
|
2
|
+
import { useCallback, useEffect, useState, useMemo, useRef } from "react";
|
|
3
3
|
import { resolveBillingApiUrl } from "@flopay/shared";
|
|
4
4
|
|
|
5
5
|
// src/context.ts
|
|
@@ -16,6 +16,59 @@ var CheckoutContext = createContext({
|
|
|
16
16
|
error: null
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
// src/telemetry-bridge.ts
|
|
20
|
+
var FLOPAY_TELEMETRY_BRIDGE = /* @__PURE__ */ Symbol.for("@flopay/js.telemetry.bridge.v1");
|
|
21
|
+
var TELEMETRY_REPORTER_FACTORY = /* @__PURE__ */ Symbol.for("@flopay/js.telemetry.reporter-factory.v1");
|
|
22
|
+
function noopTelemetryBridge() {
|
|
23
|
+
return {
|
|
24
|
+
error: () => {
|
|
25
|
+
},
|
|
26
|
+
log: () => {
|
|
27
|
+
},
|
|
28
|
+
performance: () => {
|
|
29
|
+
},
|
|
30
|
+
terminal: () => {
|
|
31
|
+
},
|
|
32
|
+
now: () => globalThis.performance?.now() ?? 0,
|
|
33
|
+
elapsed: (startedAt) => Math.max(0, (globalThis.performance?.now() ?? startedAt) - startedAt),
|
|
34
|
+
setCheckoutContext: () => {
|
|
35
|
+
},
|
|
36
|
+
beginCheckout: () => globalThis.performance?.now() ?? 0,
|
|
37
|
+
disable: () => {
|
|
38
|
+
},
|
|
39
|
+
flush: async () => {
|
|
40
|
+
},
|
|
41
|
+
destroy: () => {
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function normalizeTelemetryBridge(source) {
|
|
46
|
+
const fallback = noopTelemetryBridge();
|
|
47
|
+
const bind = (candidate, defaultValue) => candidate ? candidate.bind(source) : defaultValue;
|
|
48
|
+
const now = bind(source.now, fallback.now);
|
|
49
|
+
return {
|
|
50
|
+
error: bind(source.error, fallback.error),
|
|
51
|
+
log: bind(source.log, fallback.log),
|
|
52
|
+
performance: bind(source.performance, fallback.performance),
|
|
53
|
+
terminal: bind(source.terminal, fallback.terminal),
|
|
54
|
+
now,
|
|
55
|
+
elapsed: source.elapsed ? source.elapsed.bind(source) : (startedAt) => Math.max(0, now() - startedAt),
|
|
56
|
+
setCheckoutContext: bind(source.setCheckoutContext, fallback.setCheckoutContext),
|
|
57
|
+
beginCheckout: bind(source.beginCheckout, fallback.beginCheckout),
|
|
58
|
+
disable: bind(source.disable, fallback.disable),
|
|
59
|
+
flush: bind(source.flush, fallback.flush),
|
|
60
|
+
destroy: bind(source.destroy, fallback.destroy)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function createTelemetryBridge(options) {
|
|
64
|
+
const factory = globalThis[TELEMETRY_REPORTER_FACTORY];
|
|
65
|
+
return normalizeTelemetryBridge(factory?.(options) ?? {});
|
|
66
|
+
}
|
|
67
|
+
function getFloPayTelemetryBridge(floPay) {
|
|
68
|
+
if (!floPay) return void 0;
|
|
69
|
+
return floPay[FLOPAY_TELEMETRY_BRIDGE];
|
|
70
|
+
}
|
|
71
|
+
|
|
19
72
|
// src/provider.tsx
|
|
20
73
|
import { jsx } from "react/jsx-runtime";
|
|
21
74
|
function FloPayProvider({
|
|
@@ -31,6 +84,18 @@ function FloPayProvider({
|
|
|
31
84
|
paypalFloPayProp instanceof Promise || !paypalFloPayProp ? null : paypalFloPayProp
|
|
32
85
|
);
|
|
33
86
|
const [elements, setElements] = useState(null);
|
|
87
|
+
const mountedAt = useRef(null);
|
|
88
|
+
const renderedElements = useRef(null);
|
|
89
|
+
const interactiveElements = useRef(null);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (!flopay) return;
|
|
92
|
+
const telemetry = getFloPayTelemetryBridge(flopay);
|
|
93
|
+
mountedAt.current = telemetry?.beginCheckout() ?? telemetry?.now() ?? 0;
|
|
94
|
+
telemetry?.log({ name: "checkout.mount", stage: "checkout_mount" });
|
|
95
|
+
return () => {
|
|
96
|
+
telemetry?.log({ name: "checkout.unmount", stage: "unmount" });
|
|
97
|
+
};
|
|
98
|
+
}, [flopay]);
|
|
34
99
|
useEffect(() => {
|
|
35
100
|
let cancelled = false;
|
|
36
101
|
if (floPayProp instanceof Promise) {
|
|
@@ -91,18 +156,46 @@ function FloPayProvider({
|
|
|
91
156
|
options?.paymentMethodCreation,
|
|
92
157
|
options?.setupFutureUsage
|
|
93
158
|
]);
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
if (!flopay || !elements || renderedElements.current === elements) return;
|
|
161
|
+
renderedElements.current = elements;
|
|
162
|
+
const telemetry = getFloPayTelemetryBridge(flopay);
|
|
163
|
+
telemetry?.log({ name: "checkout.rendered", stage: "checkout_render" });
|
|
164
|
+
telemetry?.performance({
|
|
165
|
+
stage: "checkout_render",
|
|
166
|
+
durationMs: telemetry.elapsed(mountedAt.current ?? 0),
|
|
167
|
+
durationMode: "machine"
|
|
168
|
+
});
|
|
169
|
+
}, [elements, flopay]);
|
|
170
|
+
const reportInteractive = useCallback(() => {
|
|
171
|
+
if (!flopay || !elements || interactiveElements.current === elements) return;
|
|
172
|
+
interactiveElements.current = elements;
|
|
173
|
+
const telemetry = getFloPayTelemetryBridge(flopay);
|
|
174
|
+
telemetry?.log({ name: "checkout.interactive", stage: "checkout_interactive" });
|
|
175
|
+
telemetry?.performance({
|
|
176
|
+
stage: "checkout_interactive",
|
|
177
|
+
durationMs: telemetry.elapsed(mountedAt.current ?? 0),
|
|
178
|
+
durationMode: "machine"
|
|
179
|
+
});
|
|
180
|
+
}, [elements, flopay]);
|
|
94
181
|
const resolvedBillingApiUrl = resolveBillingApiUrl(options?.billingApiUrl);
|
|
95
182
|
const value = useMemo(
|
|
96
|
-
() => ({
|
|
97
|
-
|
|
183
|
+
() => ({
|
|
184
|
+
flopay,
|
|
185
|
+
paypalFlopay,
|
|
186
|
+
elements,
|
|
187
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
188
|
+
reportInteractive
|
|
189
|
+
}),
|
|
190
|
+
[flopay, paypalFlopay, elements, resolvedBillingApiUrl, reportInteractive]
|
|
98
191
|
);
|
|
99
192
|
return /* @__PURE__ */ jsx(FloPayContext.Provider, { value, children });
|
|
100
193
|
}
|
|
101
194
|
|
|
102
195
|
// src/flopay-checkout.tsx
|
|
103
|
-
import
|
|
196
|
+
import React9, { useCallback as useCallback4, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef6, useState as useState4 } from "react";
|
|
104
197
|
import { PaymentAPI as PaymentAPI4 } from "@flopay/js";
|
|
105
|
-
import { SDK_VERSION, FloPayError as FloPayError5, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme2, resolveTheme as resolveTheme2 } from "@flopay/shared";
|
|
198
|
+
import { SDK_VERSION as SDK_VERSION2, FloPayError as FloPayError5, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme2, resolveTheme as resolveTheme2 } from "@flopay/shared";
|
|
106
199
|
|
|
107
200
|
// src/card-button-content.tsx
|
|
108
201
|
import "react";
|
|
@@ -172,7 +265,7 @@ function TitleContentSlot({
|
|
|
172
265
|
}
|
|
173
266
|
|
|
174
267
|
// src/elements.tsx
|
|
175
|
-
import { useEffect as useEffect2, useRef, useContext } from "react";
|
|
268
|
+
import { useEffect as useEffect2, useRef as useRef2, useContext } from "react";
|
|
176
269
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
177
270
|
function createElementComponent(elementType, displayName) {
|
|
178
271
|
function ElementComponent({
|
|
@@ -186,9 +279,9 @@ function createElementComponent(elementType, displayName) {
|
|
|
186
279
|
onBlur,
|
|
187
280
|
onEscape
|
|
188
281
|
}) {
|
|
189
|
-
const containerRef =
|
|
190
|
-
const elementRef =
|
|
191
|
-
const { elements } = useContext(FloPayContext);
|
|
282
|
+
const containerRef = useRef2(null);
|
|
283
|
+
const elementRef = useRef2(null);
|
|
284
|
+
const { elements, reportInteractive } = useContext(FloPayContext);
|
|
192
285
|
useEffect2(() => {
|
|
193
286
|
if (!elements || !containerRef.current) return;
|
|
194
287
|
let mounted = true;
|
|
@@ -203,7 +296,10 @@ function createElementComponent(elementType, displayName) {
|
|
|
203
296
|
element.mount(containerRef.current);
|
|
204
297
|
elementRef.current = element;
|
|
205
298
|
if (onChange) element.on("change", onChange);
|
|
206
|
-
|
|
299
|
+
element.on("ready", () => {
|
|
300
|
+
reportInteractive?.();
|
|
301
|
+
onReady?.();
|
|
302
|
+
});
|
|
207
303
|
if (onFocus) element.on("focus", onFocus);
|
|
208
304
|
if (onBlur) element.on("blur", onBlur);
|
|
209
305
|
if (onEscape) element.on("escape", onEscape);
|
|
@@ -218,7 +314,7 @@ function createElementComponent(elementType, displayName) {
|
|
|
218
314
|
elementRef.current = null;
|
|
219
315
|
}
|
|
220
316
|
};
|
|
221
|
-
}, [elements]);
|
|
317
|
+
}, [elements, reportInteractive]);
|
|
222
318
|
return /* @__PURE__ */ jsx3("div", { ref: containerRef, className, id, style });
|
|
223
319
|
}
|
|
224
320
|
ElementComponent.displayName = displayName;
|
|
@@ -262,7 +358,7 @@ import {
|
|
|
262
358
|
import { PaymentAPI as PaymentAPI2 } from "@flopay/js";
|
|
263
359
|
|
|
264
360
|
// src/vault-card-fields.tsx
|
|
265
|
-
import { useEffect as useEffect3, useRef as
|
|
361
|
+
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
266
362
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
267
363
|
function VaultCardFields({
|
|
268
364
|
capture,
|
|
@@ -275,14 +371,14 @@ function VaultCardFields({
|
|
|
275
371
|
onError,
|
|
276
372
|
onValidation
|
|
277
373
|
}) {
|
|
278
|
-
const containerRef =
|
|
279
|
-
const onReadyRef =
|
|
280
|
-
const onErrorRef =
|
|
281
|
-
const onValidationRef =
|
|
374
|
+
const containerRef = useRef3(null);
|
|
375
|
+
const onReadyRef = useRef3(onReady);
|
|
376
|
+
const onErrorRef = useRef3(onError);
|
|
377
|
+
const onValidationRef = useRef3(onValidation);
|
|
282
378
|
onReadyRef.current = onReady;
|
|
283
379
|
onErrorRef.current = onError;
|
|
284
380
|
onValidationRef.current = onValidation;
|
|
285
|
-
const themeRef =
|
|
381
|
+
const themeRef = useRef3(theme);
|
|
286
382
|
themeRef.current = theme;
|
|
287
383
|
useEffect3(() => {
|
|
288
384
|
const el = containerRef.current;
|
|
@@ -332,8 +428,65 @@ function VaultCardFields({
|
|
|
332
428
|
return /* @__PURE__ */ jsx4("div", { ref: containerRef, "data-testid": "flopay-vault-card-fields", style: containerStyle });
|
|
333
429
|
}
|
|
334
430
|
|
|
431
|
+
// src/error-banner.tsx
|
|
432
|
+
import "react";
|
|
433
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
434
|
+
function ErrorBanner({
|
|
435
|
+
children,
|
|
436
|
+
margin,
|
|
437
|
+
icon = true,
|
|
438
|
+
styleOverride
|
|
439
|
+
}) {
|
|
440
|
+
return /* @__PURE__ */ jsxs2(
|
|
441
|
+
"div",
|
|
442
|
+
{
|
|
443
|
+
role: "alert",
|
|
444
|
+
"data-testid": "flopay-error",
|
|
445
|
+
style: {
|
|
446
|
+
margin,
|
|
447
|
+
padding: "0.625rem 0.875rem",
|
|
448
|
+
background: "#FEF2F2",
|
|
449
|
+
border: "1px solid #FECACA",
|
|
450
|
+
borderRadius: "8px",
|
|
451
|
+
color: "#991B1B",
|
|
452
|
+
fontSize: "0.85rem",
|
|
453
|
+
fontWeight: 600,
|
|
454
|
+
...icon ? { display: "flex", alignItems: "center", gap: "0.5rem" } : {},
|
|
455
|
+
...styleOverride ?? {}
|
|
456
|
+
},
|
|
457
|
+
children: [
|
|
458
|
+
icon && /* @__PURE__ */ jsx5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx5(
|
|
459
|
+
"path",
|
|
460
|
+
{
|
|
461
|
+
d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z",
|
|
462
|
+
stroke: "#DC2626",
|
|
463
|
+
strokeWidth: "2",
|
|
464
|
+
strokeLinecap: "round",
|
|
465
|
+
strokeLinejoin: "round"
|
|
466
|
+
}
|
|
467
|
+
) }),
|
|
468
|
+
children
|
|
469
|
+
]
|
|
470
|
+
}
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// src/payment-logos.generated.ts
|
|
475
|
+
var PAYMENT_METHOD_LOGO_URLS = {
|
|
476
|
+
"alipay": new URL("./payment-logos/alipay.svg", import.meta.url).href,
|
|
477
|
+
"bancontact": new URL("./payment-logos/bancontact.svg", import.meta.url).href,
|
|
478
|
+
"blik": new URL("./payment-logos/blik.svg", import.meta.url).href,
|
|
479
|
+
"eps": new URL("./payment-logos/eps.svg", import.meta.url).href,
|
|
480
|
+
"giropay": new URL("./payment-logos/giropay.svg", import.meta.url).href,
|
|
481
|
+
"ideal": new URL("./payment-logos/ideal.svg", import.meta.url).href,
|
|
482
|
+
"klarna": new URL("./payment-logos/klarna.svg", import.meta.url).href,
|
|
483
|
+
"p24": new URL("./payment-logos/p24.svg", import.meta.url).href,
|
|
484
|
+
"sepa_debit": new URL("./payment-logos/sepa_debit.svg", import.meta.url).href,
|
|
485
|
+
"wechat_pay": new URL("./payment-logos/wechat_pay.svg", import.meta.url).href
|
|
486
|
+
};
|
|
487
|
+
|
|
335
488
|
// src/split-card-form.tsx
|
|
336
|
-
import
|
|
489
|
+
import React8, { forwardRef, useCallback as useCallback3, useContext as useContext3, useEffect as useEffect5, useImperativeHandle, useMemo as useMemo3, useRef as useRef5, useState as useState3 } from "react";
|
|
337
490
|
|
|
338
491
|
// src/hooks.ts
|
|
339
492
|
import { useContext as useContext2 } from "react";
|
|
@@ -360,14 +513,14 @@ function useBillingApiUrl() {
|
|
|
360
513
|
|
|
361
514
|
// src/processing-overlay.tsx
|
|
362
515
|
import "react";
|
|
363
|
-
import { jsx as
|
|
516
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
364
517
|
var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
|
|
365
518
|
var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
|
|
366
519
|
function ProcessingOverlay({
|
|
367
520
|
status,
|
|
368
521
|
errorMessage
|
|
369
522
|
}) {
|
|
370
|
-
return /* @__PURE__ */
|
|
523
|
+
return /* @__PURE__ */ jsx6(
|
|
371
524
|
"div",
|
|
372
525
|
{
|
|
373
526
|
"data-testid": "flopay-processing-overlay",
|
|
@@ -384,7 +537,7 @@ function ProcessingOverlay({
|
|
|
384
537
|
zIndex: 1e3,
|
|
385
538
|
backdropFilter: "blur(2px)"
|
|
386
539
|
},
|
|
387
|
-
children: /* @__PURE__ */
|
|
540
|
+
children: /* @__PURE__ */ jsxs3(
|
|
388
541
|
"div",
|
|
389
542
|
{
|
|
390
543
|
style: {
|
|
@@ -400,8 +553,8 @@ function ProcessingOverlay({
|
|
|
400
553
|
gap: 16
|
|
401
554
|
},
|
|
402
555
|
children: [
|
|
403
|
-
/* @__PURE__ */
|
|
404
|
-
status === "processing" && /* @__PURE__ */
|
|
556
|
+
/* @__PURE__ */ jsxs3("div", { style: { width: 48, height: 48, position: "relative" }, children: [
|
|
557
|
+
status === "processing" && /* @__PURE__ */ jsxs3(
|
|
405
558
|
"svg",
|
|
406
559
|
{
|
|
407
560
|
width: "48",
|
|
@@ -411,14 +564,14 @@ function ProcessingOverlay({
|
|
|
411
564
|
xmlns: "http://www.w3.org/2000/svg",
|
|
412
565
|
style: { animation: "flopay-spin 0.8s linear infinite" },
|
|
413
566
|
children: [
|
|
414
|
-
/* @__PURE__ */
|
|
415
|
-
/* @__PURE__ */
|
|
567
|
+
/* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
|
|
568
|
+
/* @__PURE__ */ jsx6("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
|
|
416
569
|
]
|
|
417
570
|
}
|
|
418
571
|
),
|
|
419
|
-
status === "success" && /* @__PURE__ */
|
|
420
|
-
/* @__PURE__ */
|
|
421
|
-
/* @__PURE__ */
|
|
572
|
+
status === "success" && /* @__PURE__ */ jsx6("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ jsxs3("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
573
|
+
/* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
|
|
574
|
+
/* @__PURE__ */ jsx6(
|
|
422
575
|
"path",
|
|
423
576
|
{
|
|
424
577
|
d: "M7 12.5l3 3 7-7",
|
|
@@ -434,9 +587,9 @@ function ProcessingOverlay({
|
|
|
434
587
|
}
|
|
435
588
|
)
|
|
436
589
|
] }) }),
|
|
437
|
-
status === "error" && /* @__PURE__ */
|
|
438
|
-
/* @__PURE__ */
|
|
439
|
-
/* @__PURE__ */
|
|
590
|
+
status === "error" && /* @__PURE__ */ jsx6("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ jsxs3("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
591
|
+
/* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
|
|
592
|
+
/* @__PURE__ */ jsx6(
|
|
440
593
|
"path",
|
|
441
594
|
{
|
|
442
595
|
d: "M8 8l8 8M16 8l-8 8",
|
|
@@ -452,7 +605,7 @@ function ProcessingOverlay({
|
|
|
452
605
|
)
|
|
453
606
|
] }) })
|
|
454
607
|
] }),
|
|
455
|
-
/* @__PURE__ */
|
|
608
|
+
/* @__PURE__ */ jsxs3(
|
|
456
609
|
"span",
|
|
457
610
|
{
|
|
458
611
|
style: {
|
|
@@ -468,7 +621,7 @@ function ProcessingOverlay({
|
|
|
468
621
|
]
|
|
469
622
|
}
|
|
470
623
|
),
|
|
471
|
-
status === "success" && /* @__PURE__ */
|
|
624
|
+
status === "success" && /* @__PURE__ */ jsx6(
|
|
472
625
|
"p",
|
|
473
626
|
{
|
|
474
627
|
style: {
|
|
@@ -482,7 +635,7 @@ function ProcessingOverlay({
|
|
|
482
635
|
children: "You will be automatically redirected, do not close or navigate away from this window."
|
|
483
636
|
}
|
|
484
637
|
),
|
|
485
|
-
status === "error" && errorMessage && /* @__PURE__ */
|
|
638
|
+
status === "error" && errorMessage && /* @__PURE__ */ jsx6(
|
|
486
639
|
"p",
|
|
487
640
|
{
|
|
488
641
|
style: {
|
|
@@ -496,7 +649,7 @@ function ProcessingOverlay({
|
|
|
496
649
|
children: errorMessage
|
|
497
650
|
}
|
|
498
651
|
),
|
|
499
|
-
/* @__PURE__ */
|
|
652
|
+
/* @__PURE__ */ jsx6("style", { children: `
|
|
500
653
|
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
501
654
|
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
502
655
|
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
@@ -658,6 +811,14 @@ async function buildFloPayApiErrorFromResponse(response, fallbackMessage) {
|
|
|
658
811
|
const payload = await response.json().catch(() => null);
|
|
659
812
|
return buildFloPayApiError(payload, fallbackMessage);
|
|
660
813
|
}
|
|
814
|
+
function intentRequestHeaders(nonce) {
|
|
815
|
+
const headers = { "Content-Type": "application/json" };
|
|
816
|
+
if (nonce) headers["x-checkout-session-token"] = nonce;
|
|
817
|
+
return headers;
|
|
818
|
+
}
|
|
819
|
+
function isSuccessfulPaymentIntentStatus(status) {
|
|
820
|
+
return status === "succeeded" || status === "requires_capture" || status === "processing";
|
|
821
|
+
}
|
|
661
822
|
function mapPayPalIntentStatusToPaymentResult(status) {
|
|
662
823
|
if (status === "succeeded") {
|
|
663
824
|
return "succeeded";
|
|
@@ -770,10 +931,23 @@ function isInAppBrowser(userAgent) {
|
|
|
770
931
|
}
|
|
771
932
|
|
|
772
933
|
// src/direct-paypal-button.tsx
|
|
773
|
-
import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as
|
|
934
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState2 } from "react";
|
|
774
935
|
import { loadScript } from "@paypal/paypal-js";
|
|
775
936
|
import { PaymentAPI } from "@flopay/js";
|
|
776
|
-
import { FloPayError as FloPayError2, normalizeGatewayEnvironment } from "@flopay/shared";
|
|
937
|
+
import { FloPayError as FloPayError2, SDK_VERSION, normalizeGatewayEnvironment } from "@flopay/shared";
|
|
938
|
+
|
|
939
|
+
// src/merchant-callback.ts
|
|
940
|
+
function invokeMerchantCallback(callback) {
|
|
941
|
+
if (!callback) return;
|
|
942
|
+
const reportFailure = (error) => {
|
|
943
|
+
console.error("[FloPay] Merchant callback failed; checkout continued.", error);
|
|
944
|
+
};
|
|
945
|
+
try {
|
|
946
|
+
void Promise.resolve(callback()).catch(reportFailure);
|
|
947
|
+
} catch (error) {
|
|
948
|
+
reportFailure(error);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
777
951
|
|
|
778
952
|
// src/external-method-recovery.ts
|
|
779
953
|
var EXTERNAL_METHOD_CALLBACK_GRACE_MS = 600;
|
|
@@ -812,7 +986,7 @@ function isPopupBlockedError(err) {
|
|
|
812
986
|
}
|
|
813
987
|
|
|
814
988
|
// src/direct-paypal-button.tsx
|
|
815
|
-
import { jsx as
|
|
989
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
816
990
|
var DEFAULT_BUTTON_HEIGHT = 45;
|
|
817
991
|
var DIRECT_PAYPAL_RECOVERY_MESSAGE = "We couldn't open PayPal. Try again or choose another payment method.";
|
|
818
992
|
var DIRECT_PAYPAL_RECOVERY_ACTION_STYLE = {
|
|
@@ -831,7 +1005,7 @@ var DIRECT_PAYPAL_RECOVERY_ACTION_STYLE = {
|
|
|
831
1005
|
function buildDirectPayPalRecoveryMessage(popupBlocked) {
|
|
832
1006
|
return popupBlocked ? `${DIRECT_PAYPAL_RECOVERY_MESSAGE} Allow pop-ups for this site, then try again.` : DIRECT_PAYPAL_RECOVERY_MESSAGE;
|
|
833
1007
|
}
|
|
834
|
-
function
|
|
1008
|
+
function DirectPayPalButtonImplementation({
|
|
835
1009
|
sessionId,
|
|
836
1010
|
nonce,
|
|
837
1011
|
billingApiUrl,
|
|
@@ -851,14 +1025,62 @@ function DirectPayPalButton({
|
|
|
851
1025
|
runBeforeButtonClick,
|
|
852
1026
|
session,
|
|
853
1027
|
existingOrderId,
|
|
1028
|
+
telemetry,
|
|
1029
|
+
telemetryContext,
|
|
854
1030
|
debug = false
|
|
855
1031
|
}) {
|
|
856
|
-
const
|
|
857
|
-
const
|
|
858
|
-
|
|
1032
|
+
const flopay = useFloPay();
|
|
1033
|
+
const standaloneTelemetry = useMemo2(() => {
|
|
1034
|
+
if (flopay) return null;
|
|
1035
|
+
const reporter = createTelemetryBridge({
|
|
1036
|
+
billingApiUrl,
|
|
1037
|
+
sdkPackage: "@flopay/react",
|
|
1038
|
+
sdkVersion: SDK_VERSION,
|
|
1039
|
+
enabled: telemetry !== false
|
|
1040
|
+
});
|
|
1041
|
+
reporter.setCheckoutContext(telemetryContext ?? {});
|
|
1042
|
+
reporter.beginCheckout(telemetryContext ?? {});
|
|
1043
|
+
return reporter;
|
|
1044
|
+
}, [
|
|
1045
|
+
billingApiUrl,
|
|
1046
|
+
flopay,
|
|
1047
|
+
telemetry,
|
|
1048
|
+
telemetryContext?.checkoutMode,
|
|
1049
|
+
telemetryContext?.layout
|
|
1050
|
+
]);
|
|
1051
|
+
const floPayTelemetry = useMemo2(() => getFloPayTelemetryBridge(flopay), [flopay]);
|
|
1052
|
+
useEffect4(() => () => {
|
|
1053
|
+
if (!standaloneTelemetry) return;
|
|
1054
|
+
void standaloneTelemetry.flush().catch(() => {
|
|
1055
|
+
}).finally(() => standaloneTelemetry.destroy());
|
|
1056
|
+
}, [standaloneTelemetry]);
|
|
1057
|
+
const telemetrySource = useMemo2(() => ({
|
|
1058
|
+
error: (input) => {
|
|
1059
|
+
if (floPayTelemetry) floPayTelemetry.error(input);
|
|
1060
|
+
else standaloneTelemetry?.error(input);
|
|
1061
|
+
},
|
|
1062
|
+
log: (input) => {
|
|
1063
|
+
if (floPayTelemetry) floPayTelemetry.log(input);
|
|
1064
|
+
else standaloneTelemetry?.log(input);
|
|
1065
|
+
},
|
|
1066
|
+
performance: (input) => {
|
|
1067
|
+
if (floPayTelemetry) floPayTelemetry.performance(input);
|
|
1068
|
+
else standaloneTelemetry?.performance(input);
|
|
1069
|
+
},
|
|
1070
|
+
terminal: (input) => {
|
|
1071
|
+
if (floPayTelemetry) floPayTelemetry.terminal(input);
|
|
1072
|
+
else standaloneTelemetry?.terminal(input);
|
|
1073
|
+
},
|
|
1074
|
+
startTiming: () => floPayTelemetry?.now() ?? standaloneTelemetry?.now() ?? 0,
|
|
1075
|
+
elapsed: (startedAt) => floPayTelemetry?.elapsed(startedAt) ?? Math.max(0, (standaloneTelemetry?.now() ?? startedAt) - startedAt)
|
|
1076
|
+
}), [floPayTelemetry, standaloneTelemetry]);
|
|
1077
|
+
const containerRef = useRef4(null);
|
|
1078
|
+
const providerStartedAt = useRef4(0);
|
|
1079
|
+
const focusTargetRef = useRef4(null);
|
|
1080
|
+
const pendingProviderFocusRef = useRef4(false);
|
|
859
1081
|
const [ready, setReady] = useState2(false);
|
|
860
1082
|
const [renderGeneration, setRenderGeneration] = useState2(0);
|
|
861
|
-
const activeRenderGenerationRef =
|
|
1083
|
+
const activeRenderGenerationRef = useRef4(0);
|
|
862
1084
|
const [showRetryFocusTarget, setShowRetryFocusTarget] = useState2(false);
|
|
863
1085
|
const [failed, setFailed] = useState2(false);
|
|
864
1086
|
const [submitting, setSubmitting] = useState2(false);
|
|
@@ -868,23 +1090,23 @@ function DirectPayPalButton({
|
|
|
868
1090
|
if (!debug) return;
|
|
869
1091
|
setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
|
|
870
1092
|
};
|
|
871
|
-
const onTokenizedBodyRef =
|
|
872
|
-
const onCompleteRef =
|
|
873
|
-
const onErrorChangeRef =
|
|
874
|
-
const onDeclineRef =
|
|
875
|
-
const onTechnicalFailureRef =
|
|
876
|
-
const onButtonClickRef =
|
|
877
|
-
const onLoadStateChangeRef =
|
|
878
|
-
const runBeforeButtonClickRef =
|
|
879
|
-
const sessionRef =
|
|
880
|
-
const emailRef =
|
|
881
|
-
const nonceRef =
|
|
882
|
-
const beforeClickRef =
|
|
883
|
-
const attemptGenerationRef =
|
|
884
|
-
const attemptRef =
|
|
885
|
-
const invalidatedAttemptGenerationRef =
|
|
886
|
-
const attemptContextBySurfaceRef =
|
|
887
|
-
const approvalContextByTokenRef =
|
|
1093
|
+
const onTokenizedBodyRef = useRef4(onTokenizedBody);
|
|
1094
|
+
const onCompleteRef = useRef4(onComplete);
|
|
1095
|
+
const onErrorChangeRef = useRef4(onErrorChange);
|
|
1096
|
+
const onDeclineRef = useRef4(onDecline);
|
|
1097
|
+
const onTechnicalFailureRef = useRef4(onTechnicalFailure);
|
|
1098
|
+
const onButtonClickRef = useRef4(onButtonClick);
|
|
1099
|
+
const onLoadStateChangeRef = useRef4(onLoadStateChange);
|
|
1100
|
+
const runBeforeButtonClickRef = useRef4(runBeforeButtonClick);
|
|
1101
|
+
const sessionRef = useRef4(session);
|
|
1102
|
+
const emailRef = useRef4(email);
|
|
1103
|
+
const nonceRef = useRef4(nonce);
|
|
1104
|
+
const beforeClickRef = useRef4(null);
|
|
1105
|
+
const attemptGenerationRef = useRef4(0);
|
|
1106
|
+
const attemptRef = useRef4(null);
|
|
1107
|
+
const invalidatedAttemptGenerationRef = useRef4(null);
|
|
1108
|
+
const attemptContextBySurfaceRef = useRef4(/* @__PURE__ */ new Map());
|
|
1109
|
+
const approvalContextByTokenRef = useRef4(/* @__PURE__ */ new Map());
|
|
888
1110
|
useEffect4(() => {
|
|
889
1111
|
onTokenizedBodyRef.current = onTokenizedBody;
|
|
890
1112
|
}, [onTokenizedBody]);
|
|
@@ -924,16 +1146,16 @@ function DirectPayPalButton({
|
|
|
924
1146
|
useEffect4(() => {
|
|
925
1147
|
if (showRetryFocusTarget) focusTargetRef.current?.focus();
|
|
926
1148
|
}, [showRetryFocusTarget, renderGeneration]);
|
|
927
|
-
const focusRetryTarget =
|
|
1149
|
+
const focusRetryTarget = useCallback2(() => {
|
|
928
1150
|
window.setTimeout(() => {
|
|
929
1151
|
focusTargetRef.current?.focus();
|
|
930
1152
|
}, 0);
|
|
931
1153
|
}, []);
|
|
932
|
-
const remountPayPalButtons =
|
|
1154
|
+
const remountPayPalButtons = useCallback2(() => {
|
|
933
1155
|
setReady(false);
|
|
934
1156
|
setRenderGeneration((current) => current + 1);
|
|
935
1157
|
}, []);
|
|
936
|
-
const focusPayPalSurface =
|
|
1158
|
+
const focusPayPalSurface = useCallback2(() => {
|
|
937
1159
|
setShowRetryFocusTarget(false);
|
|
938
1160
|
const target = containerRef.current?.querySelector(
|
|
939
1161
|
'iframe, button, [tabindex]:not([tabindex="-1"])'
|
|
@@ -945,7 +1167,7 @@ function DirectPayPalButton({
|
|
|
945
1167
|
pendingProviderFocusRef.current = false;
|
|
946
1168
|
focusPayPalSurface();
|
|
947
1169
|
}, [focusPayPalSurface, ready, renderGeneration]);
|
|
948
|
-
const notifyTechnicalFailure =
|
|
1170
|
+
const notifyTechnicalFailure = useCallback2((err, options) => {
|
|
949
1171
|
const handler = onTechnicalFailureRef.current;
|
|
950
1172
|
if (handler) {
|
|
951
1173
|
handler("paypal", err, options);
|
|
@@ -1042,7 +1264,7 @@ function DirectPayPalButton({
|
|
|
1042
1264
|
};
|
|
1043
1265
|
}, []);
|
|
1044
1266
|
useEffect4(() => {
|
|
1045
|
-
onLoadStateChangeRef.current?.(ready && !failed);
|
|
1267
|
+
invokeMerchantCallback(() => onLoadStateChangeRef.current?.(ready && !failed));
|
|
1046
1268
|
}, [ready, failed]);
|
|
1047
1269
|
const normalizedEnv = normalizeGatewayEnvironment(environment);
|
|
1048
1270
|
useEffect4(() => {
|
|
@@ -1053,6 +1275,13 @@ function DirectPayPalButton({
|
|
|
1053
1275
|
if (!clientId) {
|
|
1054
1276
|
appendDebug("FAIL: clientId empty \u2014 gateway misconfigured");
|
|
1055
1277
|
setFailed(true);
|
|
1278
|
+
telemetrySource.error({
|
|
1279
|
+
errorCode: "CONFIGURATION_INVALID",
|
|
1280
|
+
stage: "provider_load",
|
|
1281
|
+
provider: "paypal",
|
|
1282
|
+
paymentMethodCategory: "paypal",
|
|
1283
|
+
requestCategory: "provider_sdk"
|
|
1284
|
+
});
|
|
1056
1285
|
console.error("[FloPay] DirectPayPal: clientId empty \u2014 gateway misconfigured");
|
|
1057
1286
|
return;
|
|
1058
1287
|
}
|
|
@@ -1060,8 +1289,33 @@ function DirectPayPalButton({
|
|
|
1060
1289
|
appendDebug("FAIL: containerRef not attached");
|
|
1061
1290
|
return;
|
|
1062
1291
|
}
|
|
1292
|
+
providerStartedAt.current = telemetrySource.startTiming();
|
|
1293
|
+
telemetrySource.log({
|
|
1294
|
+
name: "provider.load.started",
|
|
1295
|
+
stage: "provider_load",
|
|
1296
|
+
provider: "paypal",
|
|
1297
|
+
paymentMethodCategory: "paypal"
|
|
1298
|
+
});
|
|
1063
1299
|
let cancelled = false;
|
|
1064
1300
|
let activeButtons = null;
|
|
1301
|
+
let overlayStartedAt = null;
|
|
1302
|
+
const finishOverlay = () => {
|
|
1303
|
+
if (overlayStartedAt === null) return;
|
|
1304
|
+
telemetrySource.log({
|
|
1305
|
+
name: "provider.overlay.returned",
|
|
1306
|
+
stage: "overlay_return",
|
|
1307
|
+
provider: "paypal",
|
|
1308
|
+
paymentMethodCategory: "paypal"
|
|
1309
|
+
});
|
|
1310
|
+
telemetrySource.performance({
|
|
1311
|
+
stage: "overlay_return",
|
|
1312
|
+
durationMs: telemetrySource.elapsed(overlayStartedAt),
|
|
1313
|
+
durationMode: "buyer",
|
|
1314
|
+
provider: "paypal",
|
|
1315
|
+
paymentMethodCategory: "paypal"
|
|
1316
|
+
});
|
|
1317
|
+
overlayStartedAt = null;
|
|
1318
|
+
};
|
|
1065
1319
|
let rendered = false;
|
|
1066
1320
|
const container = containerRef.current;
|
|
1067
1321
|
let containerObserver = null;
|
|
@@ -1165,7 +1419,7 @@ function DirectPayPalButton({
|
|
|
1165
1419
|
if (cancelled) return;
|
|
1166
1420
|
if (isZoidLifecycleMessage(message)) return;
|
|
1167
1421
|
const friendly = applyFriendlyMessageOverride(message) ?? message;
|
|
1168
|
-
onErrorChangeRef.current?.(friendly);
|
|
1422
|
+
invokeMerchantCallback(() => onErrorChangeRef.current?.(friendly));
|
|
1169
1423
|
};
|
|
1170
1424
|
const markRenderFailed = (message) => {
|
|
1171
1425
|
if (cancelled) return;
|
|
@@ -1174,24 +1428,55 @@ function DirectPayPalButton({
|
|
|
1174
1428
|
return;
|
|
1175
1429
|
}
|
|
1176
1430
|
setFailed(true);
|
|
1431
|
+
if (!message.includes("paypal_ineligible")) {
|
|
1432
|
+
telemetrySource.error({
|
|
1433
|
+
errorCode: "PROVIDER_LOAD_FAILED",
|
|
1434
|
+
stage: "provider_load",
|
|
1435
|
+
provider: "paypal",
|
|
1436
|
+
paymentMethodCategory: "paypal",
|
|
1437
|
+
requestCategory: "provider_sdk"
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1177
1440
|
console.error("[FloPay] DirectPayPal load/render failure:", message);
|
|
1178
1441
|
};
|
|
1179
1442
|
setFailed(false);
|
|
1180
1443
|
const dispatchTokenizedBody = async (body, prepared = beforeClickRef.current) => {
|
|
1181
1444
|
const effectiveSessionId = prepared?.sessionId ?? sessionId;
|
|
1182
1445
|
if (onTokenizedBodyRef.current) {
|
|
1183
|
-
onTokenizedBodyRef.current(body, {
|
|
1446
|
+
await onTokenizedBodyRef.current(body, {
|
|
1184
1447
|
sessionId: effectiveSessionId,
|
|
1185
1448
|
accountPatch: prepared?.accountPatch,
|
|
1186
1449
|
nonce: prepared?.nonce
|
|
1187
1450
|
});
|
|
1188
1451
|
return;
|
|
1189
1452
|
}
|
|
1453
|
+
const processingStartedAt = telemetrySource.startTiming();
|
|
1454
|
+
telemetrySource.log({
|
|
1455
|
+
name: "payment.processing.started",
|
|
1456
|
+
stage: "processing",
|
|
1457
|
+
provider: "paypal",
|
|
1458
|
+
paymentMethodCategory: "paypal"
|
|
1459
|
+
});
|
|
1460
|
+
const finishProcessing = () => {
|
|
1461
|
+
telemetrySource.log({
|
|
1462
|
+
name: "payment.processing.completed",
|
|
1463
|
+
stage: "processing",
|
|
1464
|
+
provider: "paypal",
|
|
1465
|
+
paymentMethodCategory: "paypal"
|
|
1466
|
+
});
|
|
1467
|
+
telemetrySource.performance({
|
|
1468
|
+
stage: "processing",
|
|
1469
|
+
durationMs: telemetrySource.elapsed(processingStartedAt),
|
|
1470
|
+
durationMode: "machine",
|
|
1471
|
+
provider: "paypal",
|
|
1472
|
+
paymentMethodCategory: "paypal"
|
|
1473
|
+
});
|
|
1474
|
+
};
|
|
1190
1475
|
try {
|
|
1191
1476
|
const currentSession = sessionRef.current;
|
|
1192
1477
|
const currentEmail = prepared?.accountPatch?.email ?? emailRef.current;
|
|
1193
1478
|
const effectiveUserId = prepared?.accountPatch?.userId ?? currentSession?.customer?.id ?? currentSession?.accountData?.userId ?? "";
|
|
1194
|
-
const api = new PaymentAPI(baseUrl);
|
|
1479
|
+
const api = new PaymentAPI(baseUrl, { telemetry: false });
|
|
1195
1480
|
const response = await api.processPayment(
|
|
1196
1481
|
effectiveUserId,
|
|
1197
1482
|
{
|
|
@@ -1209,31 +1494,71 @@ function DirectPayPalButton({
|
|
|
1209
1494
|
}
|
|
1210
1495
|
);
|
|
1211
1496
|
if (response.ok) {
|
|
1212
|
-
|
|
1497
|
+
finishProcessing();
|
|
1498
|
+
telemetrySource.terminal({
|
|
1499
|
+
outcome: "payment_succeeded",
|
|
1500
|
+
provider: "paypal",
|
|
1501
|
+
paymentMethodCategory: "paypal"
|
|
1502
|
+
});
|
|
1503
|
+
} else {
|
|
1504
|
+
const json = await response.json().catch(() => null);
|
|
1505
|
+
const rawMessage = json?.["message"] ?? "PayPal payment failed.";
|
|
1506
|
+
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
1507
|
+
finishProcessing();
|
|
1508
|
+
if (typeof json?.["declineCode"] === "string") {
|
|
1509
|
+
telemetrySource.terminal({
|
|
1510
|
+
outcome: "payment_declined",
|
|
1511
|
+
provider: "paypal",
|
|
1512
|
+
paymentMethodCategory: "paypal"
|
|
1513
|
+
});
|
|
1514
|
+
} else {
|
|
1515
|
+
telemetrySource.error({
|
|
1516
|
+
errorCode: "PAYMENT_PROCESSING_FAILED",
|
|
1517
|
+
stage: "processing",
|
|
1518
|
+
provider: "paypal",
|
|
1519
|
+
paymentMethodCategory: "paypal",
|
|
1520
|
+
requestCategory: "process_payment",
|
|
1521
|
+
statusClass: response.status >= 500 ? "5xx" : response.status >= 400 ? "4xx" : response.status >= 300 ? "3xx" : "unknown"
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
forwardError(message);
|
|
1525
|
+
invokeMerchantCallback(() => onDeclineRef.current?.(buildDeclineEvent("paypal", message, {
|
|
1526
|
+
code: json?.["code"],
|
|
1527
|
+
declineCode: json?.["declineCode"]
|
|
1528
|
+
})));
|
|
1213
1529
|
return;
|
|
1214
1530
|
}
|
|
1215
|
-
const json = await response.json().catch(() => null);
|
|
1216
|
-
const rawMessage = json?.["message"] ?? "PayPal payment failed.";
|
|
1217
|
-
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
1218
|
-
forwardError(message);
|
|
1219
|
-
onDeclineRef.current?.(buildDeclineEvent("paypal", message, {
|
|
1220
|
-
code: json?.["code"],
|
|
1221
|
-
declineCode: json?.["declineCode"]
|
|
1222
|
-
}));
|
|
1223
1531
|
} catch (err) {
|
|
1532
|
+
finishProcessing();
|
|
1533
|
+
telemetrySource.error({
|
|
1534
|
+
errorCode: "NETWORK_REQUEST_FAILED",
|
|
1535
|
+
stage: "processing",
|
|
1536
|
+
provider: "paypal",
|
|
1537
|
+
paymentMethodCategory: "paypal",
|
|
1538
|
+
requestCategory: "process_payment",
|
|
1539
|
+
statusClass: "network_error"
|
|
1540
|
+
});
|
|
1224
1541
|
const rawMessage = err instanceof Error ? err.message : "PayPal payment failed.";
|
|
1225
1542
|
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
1226
1543
|
forwardError(message);
|
|
1227
|
-
onDeclineRef.current?.(buildDeclineEvent("paypal", message));
|
|
1544
|
+
invokeMerchantCallback(() => onDeclineRef.current?.(buildDeclineEvent("paypal", message)));
|
|
1545
|
+
return;
|
|
1228
1546
|
}
|
|
1547
|
+
invokeMerchantCallback(() => onCompleteRef.current?.({ status: "succeeded", checkoutMethod: "paypal" }));
|
|
1229
1548
|
};
|
|
1230
1549
|
const createPaypalIntent = async (fallbackMessage) => {
|
|
1231
1550
|
const prepared = beforeClickRef.current;
|
|
1232
1551
|
const effectiveSessionId = prepared?.sessionId ?? sessionId;
|
|
1233
1552
|
const effectiveEmail = prepared?.accountPatch?.email ?? emailRef.current;
|
|
1234
|
-
const intentHeaders = { "Content-Type": "application/json" };
|
|
1235
1553
|
const currentNonce = prepared?.nonce ?? nonceRef.current;
|
|
1236
|
-
|
|
1554
|
+
const intentHeaders = intentRequestHeaders(currentNonce);
|
|
1555
|
+
telemetrySource.log({
|
|
1556
|
+
name: "payment.intent.started",
|
|
1557
|
+
stage: "processing",
|
|
1558
|
+
provider: "paypal",
|
|
1559
|
+
paymentMethodCategory: "paypal",
|
|
1560
|
+
requestCategory: "intent_create"
|
|
1561
|
+
});
|
|
1237
1562
|
const response = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
1238
1563
|
method: "POST",
|
|
1239
1564
|
headers: intentHeaders,
|
|
@@ -1252,6 +1577,14 @@ function DirectPayPalButton({
|
|
|
1252
1577
|
if (!id) {
|
|
1253
1578
|
throw new Error(fallbackMessage);
|
|
1254
1579
|
}
|
|
1580
|
+
telemetrySource.log({
|
|
1581
|
+
name: "payment.intent.completed",
|
|
1582
|
+
stage: "processing",
|
|
1583
|
+
provider: "paypal",
|
|
1584
|
+
paymentMethodCategory: "paypal",
|
|
1585
|
+
requestCategory: "intent_create",
|
|
1586
|
+
statusClass: "2xx"
|
|
1587
|
+
});
|
|
1255
1588
|
return id;
|
|
1256
1589
|
};
|
|
1257
1590
|
const effectRenderGeneration = renderGeneration;
|
|
@@ -1286,6 +1619,12 @@ function DirectPayPalButton({
|
|
|
1286
1619
|
if (!cancelled && !paypal?.Buttons) appendDebug("FAIL: namespace missing Buttons factory");
|
|
1287
1620
|
return;
|
|
1288
1621
|
}
|
|
1622
|
+
telemetrySource.log({
|
|
1623
|
+
name: "provider.availability.checked",
|
|
1624
|
+
stage: "provider_ready",
|
|
1625
|
+
provider: "paypal",
|
|
1626
|
+
paymentMethodCategory: "paypal"
|
|
1627
|
+
});
|
|
1289
1628
|
const handleApprove = async (data) => {
|
|
1290
1629
|
if (cancelled || activeRenderGenerationRef.current !== effectRenderGeneration) return;
|
|
1291
1630
|
const token = data.subscriptionID ?? data.orderID ?? "";
|
|
@@ -1294,9 +1633,10 @@ function DirectPayPalButton({
|
|
|
1294
1633
|
if (!finishAttempt(context.generation)) return;
|
|
1295
1634
|
approvalContextByTokenRef.current.delete(token);
|
|
1296
1635
|
attemptContextBySurfaceRef.current.delete(context.surfaceKey);
|
|
1636
|
+
finishOverlay();
|
|
1297
1637
|
try {
|
|
1298
1638
|
setSubmitting(true);
|
|
1299
|
-
onErrorChangeRef.current?.(null);
|
|
1639
|
+
invokeMerchantCallback(() => onErrorChangeRef.current?.(null));
|
|
1300
1640
|
if (!token) {
|
|
1301
1641
|
throw new FloPayError2(
|
|
1302
1642
|
"PayPal did not return an approval token.",
|
|
@@ -1346,7 +1686,7 @@ function DirectPayPalButton({
|
|
|
1346
1686
|
return;
|
|
1347
1687
|
}
|
|
1348
1688
|
}
|
|
1349
|
-
onButtonClickRef.current?.("paypal");
|
|
1689
|
+
invokeMerchantCallback(() => onButtonClickRef.current?.("paypal"));
|
|
1350
1690
|
const generation = startAttempt();
|
|
1351
1691
|
const context = {
|
|
1352
1692
|
generation,
|
|
@@ -1356,6 +1696,25 @@ function DirectPayPalButton({
|
|
|
1356
1696
|
beforeClickRef.current = context;
|
|
1357
1697
|
attemptContextBySurfaceRef.current.set(effectRenderGeneration, context);
|
|
1358
1698
|
await actions.resolve();
|
|
1699
|
+
telemetrySource.log({
|
|
1700
|
+
name: "payment.method.selected",
|
|
1701
|
+
stage: "processing",
|
|
1702
|
+
provider: "paypal",
|
|
1703
|
+
paymentMethodCategory: "paypal"
|
|
1704
|
+
});
|
|
1705
|
+
telemetrySource.log({
|
|
1706
|
+
name: "provider.popup.opened",
|
|
1707
|
+
stage: "overlay_open",
|
|
1708
|
+
provider: "paypal",
|
|
1709
|
+
paymentMethodCategory: "paypal"
|
|
1710
|
+
});
|
|
1711
|
+
telemetrySource.log({
|
|
1712
|
+
name: "provider.overlay.opened",
|
|
1713
|
+
stage: "overlay_open",
|
|
1714
|
+
provider: "paypal",
|
|
1715
|
+
paymentMethodCategory: "paypal"
|
|
1716
|
+
});
|
|
1717
|
+
overlayStartedAt = telemetrySource.startTiming();
|
|
1359
1718
|
},
|
|
1360
1719
|
// When the SDK is already holding an order/subscription id from a
|
|
1361
1720
|
// prior backend round-trip (the `paypal_direct_required` retry
|
|
@@ -1368,6 +1727,12 @@ function DirectPayPalButton({
|
|
|
1368
1727
|
const context = attemptContextBySurfaceRef.current.get(effectRenderGeneration) ?? beforeClickRef.current;
|
|
1369
1728
|
if (context) attemptContextBySurfaceRef.current.delete(context.surfaceKey);
|
|
1370
1729
|
beforeClickRef.current = null;
|
|
1730
|
+
finishOverlay();
|
|
1731
|
+
telemetrySource.terminal({
|
|
1732
|
+
outcome: "payment_cancelled",
|
|
1733
|
+
provider: "paypal",
|
|
1734
|
+
paymentMethodCategory: "paypal"
|
|
1735
|
+
});
|
|
1371
1736
|
pendingProviderFocusRef.current = true;
|
|
1372
1737
|
invalidateAttempt({ generation: context?.generation, remount: true, focus: false });
|
|
1373
1738
|
},
|
|
@@ -1383,6 +1748,15 @@ function DirectPayPalButton({
|
|
|
1383
1748
|
finishAttempt(context?.generation);
|
|
1384
1749
|
return;
|
|
1385
1750
|
}
|
|
1751
|
+
finishOverlay();
|
|
1752
|
+
const lower = message.toLowerCase();
|
|
1753
|
+
telemetrySource.error({
|
|
1754
|
+
errorCode: lower.includes("popup") && lower.includes("block") ? "POPUP_BLOCKED" : "PROVIDER_RUNTIME_FAILED",
|
|
1755
|
+
stage: "provider_ready",
|
|
1756
|
+
provider: "paypal",
|
|
1757
|
+
paymentMethodCategory: "paypal",
|
|
1758
|
+
requestCategory: "provider_sdk"
|
|
1759
|
+
});
|
|
1386
1760
|
if (context) attemptContextBySurfaceRef.current.delete(context.surfaceKey);
|
|
1387
1761
|
beforeClickRef.current = null;
|
|
1388
1762
|
invalidateAttempt({ generation: context?.generation, remount: true, showRetry: true, focus: true });
|
|
@@ -1394,6 +1768,12 @@ function DirectPayPalButton({
|
|
|
1394
1768
|
});
|
|
1395
1769
|
const eligible = buttons.isEligible();
|
|
1396
1770
|
appendDebug(`isEligible=${eligible}`);
|
|
1771
|
+
telemetrySource.log({
|
|
1772
|
+
name: "provider.eligibility.checked",
|
|
1773
|
+
stage: "provider_ready",
|
|
1774
|
+
provider: "paypal",
|
|
1775
|
+
paymentMethodCategory: "paypal"
|
|
1776
|
+
});
|
|
1397
1777
|
if (!eligible) {
|
|
1398
1778
|
setReady(false);
|
|
1399
1779
|
markRenderFailed(
|
|
@@ -1465,6 +1845,19 @@ function DirectPayPalButton({
|
|
|
1465
1845
|
activeButtons = typedButtons;
|
|
1466
1846
|
rendered = true;
|
|
1467
1847
|
setReady(true);
|
|
1848
|
+
telemetrySource.log({
|
|
1849
|
+
name: "provider.ready",
|
|
1850
|
+
stage: "provider_ready",
|
|
1851
|
+
provider: "paypal",
|
|
1852
|
+
paymentMethodCategory: "paypal"
|
|
1853
|
+
});
|
|
1854
|
+
telemetrySource.performance({
|
|
1855
|
+
stage: "provider_ready",
|
|
1856
|
+
durationMs: telemetrySource.elapsed(providerStartedAt.current),
|
|
1857
|
+
durationMode: "machine",
|
|
1858
|
+
provider: "paypal",
|
|
1859
|
+
paymentMethodCategory: "paypal"
|
|
1860
|
+
});
|
|
1468
1861
|
}).catch((err) => {
|
|
1469
1862
|
const message = err instanceof Error ? err.message : "PayPal failed to render.";
|
|
1470
1863
|
appendDebug(`render:rejected msg=${message.slice(0, 120)}`);
|
|
@@ -1486,8 +1879,8 @@ function DirectPayPalButton({
|
|
|
1486
1879
|
});
|
|
1487
1880
|
}
|
|
1488
1881
|
};
|
|
1489
|
-
}, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId, renderGeneration]);
|
|
1490
|
-
const debugPanel = debug ? /* @__PURE__ */
|
|
1882
|
+
}, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId, renderGeneration, telemetrySource]);
|
|
1883
|
+
const debugPanel = debug ? /* @__PURE__ */ jsxs4(
|
|
1491
1884
|
"pre",
|
|
1492
1885
|
{
|
|
1493
1886
|
"data-testid": "flopay-direct-paypal-debug",
|
|
@@ -1512,17 +1905,17 @@ ${debugLines.join("\n")}`
|
|
|
1512
1905
|
}
|
|
1513
1906
|
) : null;
|
|
1514
1907
|
if (failed) {
|
|
1515
|
-
return debug ? /* @__PURE__ */
|
|
1908
|
+
return debug ? /* @__PURE__ */ jsx7("div", { children: debugPanel }) : null;
|
|
1516
1909
|
}
|
|
1517
1910
|
return (
|
|
1518
1911
|
// Single wrapper so the parent flex container sees exactly one flex item
|
|
1519
1912
|
// (otherwise the fragment's placeholder + container become two siblings
|
|
1520
1913
|
// and any spacing-sensitive layout has to reason about both). The wrapper
|
|
1521
1914
|
// intentionally has no margin/padding so the parent owns all spacing.
|
|
1522
|
-
/* @__PURE__ */
|
|
1915
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1523
1916
|
debugPanel,
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
!ready && /* @__PURE__ */
|
|
1917
|
+
/* @__PURE__ */ jsxs4("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
|
|
1918
|
+
!ready && /* @__PURE__ */ jsx7(
|
|
1526
1919
|
"div",
|
|
1527
1920
|
{
|
|
1528
1921
|
"data-testid": "flopay-direct-paypal-placeholder",
|
|
@@ -1536,7 +1929,7 @@ ${debugLines.join("\n")}`
|
|
|
1536
1929
|
}
|
|
1537
1930
|
}
|
|
1538
1931
|
),
|
|
1539
|
-
/* @__PURE__ */
|
|
1932
|
+
/* @__PURE__ */ jsx7(
|
|
1540
1933
|
"div",
|
|
1541
1934
|
{
|
|
1542
1935
|
ref: containerRef,
|
|
@@ -1553,7 +1946,7 @@ ${debugLines.join("\n")}`
|
|
|
1553
1946
|
renderGeneration
|
|
1554
1947
|
)
|
|
1555
1948
|
] }),
|
|
1556
|
-
showRetryFocusTarget && /* @__PURE__ */
|
|
1949
|
+
showRetryFocusTarget && /* @__PURE__ */ jsx7(
|
|
1557
1950
|
"button",
|
|
1558
1951
|
{
|
|
1559
1952
|
ref: focusTargetRef,
|
|
@@ -1567,10 +1960,16 @@ ${debugLines.join("\n")}`
|
|
|
1567
1960
|
] })
|
|
1568
1961
|
);
|
|
1569
1962
|
}
|
|
1963
|
+
function DirectPayPalButton(props) {
|
|
1964
|
+
return /* @__PURE__ */ jsx7(DirectPayPalButtonImplementation, { ...props });
|
|
1965
|
+
}
|
|
1966
|
+
function InstrumentedDirectPayPalButton(props) {
|
|
1967
|
+
return /* @__PURE__ */ jsx7(DirectPayPalButtonImplementation, { ...props });
|
|
1968
|
+
}
|
|
1570
1969
|
|
|
1571
1970
|
// src/split-card-form.tsx
|
|
1572
1971
|
import { FloPayError as FloPayError3, isSetupIntentClientSecret as isSetupIntentClientSecret2, resolveTheme } from "@flopay/shared";
|
|
1573
|
-
import { Fragment as Fragment2, jsx as
|
|
1972
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1574
1973
|
var STRIPE_RESUME_KEY = "flopay_stripe_resume";
|
|
1575
1974
|
var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
1576
1975
|
var PAYPAL_RESUME_KEY = "flopay_paypal_resume";
|
|
@@ -1685,17 +2084,17 @@ function buildExternalMethodRecoveryMessage(method, popupBlocked) {
|
|
|
1685
2084
|
return popupBlocked ? `${base} Allow pop-ups for this site, then try again.` : base;
|
|
1686
2085
|
}
|
|
1687
2086
|
function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
1688
|
-
const generationRef =
|
|
1689
|
-
const invalidatedGenerationRef =
|
|
1690
|
-
const attemptRef =
|
|
1691
|
-
const clearAttemptTimer =
|
|
2087
|
+
const generationRef = useRef5(0);
|
|
2088
|
+
const invalidatedGenerationRef = useRef5(null);
|
|
2089
|
+
const attemptRef = useRef5(null);
|
|
2090
|
+
const clearAttemptTimer = useCallback3((targetAttempt = attemptRef.current) => {
|
|
1692
2091
|
const attempt = targetAttempt;
|
|
1693
2092
|
if (attempt?.timer) {
|
|
1694
2093
|
clearTimeout(attempt.timer);
|
|
1695
2094
|
attempt.timer = null;
|
|
1696
2095
|
}
|
|
1697
2096
|
}, []);
|
|
1698
|
-
const armAttemptTimer =
|
|
2097
|
+
const armAttemptTimer = useCallback3((attempt, delayMs) => {
|
|
1699
2098
|
if (typeof document !== "undefined" && document.visibilityState !== "visible") return;
|
|
1700
2099
|
clearAttemptTimer(attempt);
|
|
1701
2100
|
attempt.timer = setTimeout(() => {
|
|
@@ -1710,11 +2109,11 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1710
2109
|
);
|
|
1711
2110
|
}, delayMs);
|
|
1712
2111
|
}, [clearAttemptTimer, onMissingTerminal]);
|
|
1713
|
-
const armRecoveryTimer =
|
|
2112
|
+
const armRecoveryTimer = useCallback3((attempt) => {
|
|
1714
2113
|
if (!attempt.yieldedControl) return;
|
|
1715
2114
|
armAttemptTimer(attempt, EXTERNAL_METHOD_CALLBACK_GRACE_MS);
|
|
1716
2115
|
}, [armAttemptTimer]);
|
|
1717
|
-
const startAttempt =
|
|
2116
|
+
const startAttempt = useCallback3((method) => {
|
|
1718
2117
|
clearAttemptTimer();
|
|
1719
2118
|
const generation = generationRef.current + 1;
|
|
1720
2119
|
generationRef.current = generation;
|
|
@@ -1723,7 +2122,7 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1723
2122
|
attemptRef.current = attempt;
|
|
1724
2123
|
return generation;
|
|
1725
2124
|
}, [clearAttemptTimer]);
|
|
1726
|
-
const finishAttempt =
|
|
2125
|
+
const finishAttempt = useCallback3((generation) => {
|
|
1727
2126
|
const attempt = attemptRef.current;
|
|
1728
2127
|
if (typeof generation === "number" && attempt?.generation !== generation) return false;
|
|
1729
2128
|
clearAttemptTimer(attempt);
|
|
@@ -1733,7 +2132,7 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1733
2132
|
}
|
|
1734
2133
|
return true;
|
|
1735
2134
|
}, [clearAttemptTimer]);
|
|
1736
|
-
const invalidateAttempt =
|
|
2135
|
+
const invalidateAttempt = useCallback3((generation) => {
|
|
1737
2136
|
const attempt = attemptRef.current;
|
|
1738
2137
|
const targetGeneration = generation ?? attempt?.generation ?? generationRef.current;
|
|
1739
2138
|
if (!generation || attempt?.generation === generation) {
|
|
@@ -1742,20 +2141,20 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
|
|
|
1742
2141
|
}
|
|
1743
2142
|
invalidatedGenerationRef.current = targetGeneration;
|
|
1744
2143
|
}, [clearAttemptTimer]);
|
|
1745
|
-
const isAttemptInvalidated =
|
|
2144
|
+
const isAttemptInvalidated = useCallback3(
|
|
1746
2145
|
(generation) => invalidatedGenerationRef.current === (generation ?? generationRef.current),
|
|
1747
2146
|
[]
|
|
1748
2147
|
);
|
|
1749
|
-
const isAttemptCurrent =
|
|
2148
|
+
const isAttemptCurrent = useCallback3(
|
|
1750
2149
|
(generation) => attemptRef.current?.generation === generation && invalidatedGenerationRef.current !== generation,
|
|
1751
2150
|
[]
|
|
1752
2151
|
);
|
|
1753
|
-
const scheduleRecoveryIfReturned =
|
|
2152
|
+
const scheduleRecoveryIfReturned = useCallback3(() => {
|
|
1754
2153
|
const attempt = attemptRef.current;
|
|
1755
2154
|
if (!attempt) return;
|
|
1756
2155
|
armRecoveryTimer(attempt);
|
|
1757
2156
|
}, [armRecoveryTimer]);
|
|
1758
|
-
const markAttemptYieldedControl =
|
|
2157
|
+
const markAttemptYieldedControl = useCallback3(() => {
|
|
1759
2158
|
const attempt = attemptRef.current;
|
|
1760
2159
|
if (!attempt) return;
|
|
1761
2160
|
attempt.yieldedControl = true;
|
|
@@ -1803,7 +2202,7 @@ function normalizeBeforeButtonClickError(method, err) {
|
|
|
1803
2202
|
);
|
|
1804
2203
|
}
|
|
1805
2204
|
function FloPayKeyframes() {
|
|
1806
|
-
return /* @__PURE__ */
|
|
2205
|
+
return /* @__PURE__ */ jsx8("style", { children: FLOPAY_KEYFRAMES });
|
|
1807
2206
|
}
|
|
1808
2207
|
function toCssSize(value) {
|
|
1809
2208
|
if (typeof value === "number") return `${value}px`;
|
|
@@ -1825,8 +2224,8 @@ function ExpressCheckoutReadySwap({
|
|
|
1825
2224
|
children
|
|
1826
2225
|
}) {
|
|
1827
2226
|
if (state === "unavailable" || state === "load_error") return null;
|
|
1828
|
-
return /* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
2227
|
+
return /* @__PURE__ */ jsxs5("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
2228
|
+
/* @__PURE__ */ jsx8(
|
|
1830
2229
|
"div",
|
|
1831
2230
|
{
|
|
1832
2231
|
"data-testid": placeholderTestId,
|
|
@@ -1845,7 +2244,7 @@ function ExpressCheckoutReadySwap({
|
|
|
1845
2244
|
}
|
|
1846
2245
|
}
|
|
1847
2246
|
),
|
|
1848
|
-
/* @__PURE__ */
|
|
2247
|
+
/* @__PURE__ */ jsx8(
|
|
1849
2248
|
"div",
|
|
1850
2249
|
{
|
|
1851
2250
|
style: {
|
|
@@ -1865,7 +2264,7 @@ function isExpressCheckoutRowVisible(state) {
|
|
|
1865
2264
|
}
|
|
1866
2265
|
var SplitCardForm = forwardRef(
|
|
1867
2266
|
function SplitCardForm2(props, ref) {
|
|
1868
|
-
return /* @__PURE__ */
|
|
2267
|
+
return /* @__PURE__ */ jsx8(SplitCardFormInner, { ...props, innerRef: ref });
|
|
1869
2268
|
}
|
|
1870
2269
|
);
|
|
1871
2270
|
function PayPalButtonInner({
|
|
@@ -1883,6 +2282,7 @@ function PayPalButtonInner({
|
|
|
1883
2282
|
onLoadStateChange,
|
|
1884
2283
|
placeholderBorderRadius
|
|
1885
2284
|
}) {
|
|
2285
|
+
const flopay = useFloPay();
|
|
1886
2286
|
const stripe = useStripeRaw();
|
|
1887
2287
|
const elements = useStripeElements();
|
|
1888
2288
|
const [loadState, setLoadState] = useState3("loading");
|
|
@@ -1890,13 +2290,13 @@ function PayPalButtonInner({
|
|
|
1890
2290
|
onLoadStateChange?.(loadState);
|
|
1891
2291
|
}, [loadState, onLoadStateChange]);
|
|
1892
2292
|
const [submitting, setSubmitting] = useState3(false);
|
|
1893
|
-
const paypalResumeAttempted =
|
|
1894
|
-
const focusTargetRef =
|
|
1895
|
-
const recoveryActionRef =
|
|
2293
|
+
const paypalResumeAttempted = useRef5(false);
|
|
2294
|
+
const focusTargetRef = useRef5(null);
|
|
2295
|
+
const recoveryActionRef = useRef5(null);
|
|
1896
2296
|
const [surfaceKey, setSurfaceKey] = useState3(0);
|
|
1897
2297
|
const [showRecoveryAction, setShowRecoveryAction] = useState3(false);
|
|
1898
|
-
const pendingProviderFocusRef =
|
|
1899
|
-
const attemptContextBySurfaceRef =
|
|
2298
|
+
const pendingProviderFocusRef = useRef5(false);
|
|
2299
|
+
const attemptContextBySurfaceRef = useRef5(/* @__PURE__ */ new Map());
|
|
1900
2300
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
1901
2301
|
const {
|
|
1902
2302
|
startAttempt,
|
|
@@ -1915,16 +2315,16 @@ function PayPalButtonInner({
|
|
|
1915
2315
|
useEffect5(() => {
|
|
1916
2316
|
if (showRecoveryAction) recoveryActionRef.current?.focus();
|
|
1917
2317
|
}, [showRecoveryAction, surfaceKey]);
|
|
1918
|
-
const resetSurface =
|
|
2318
|
+
const resetSurface = useCallback3(() => {
|
|
1919
2319
|
setSurfaceKey((key) => key + 1);
|
|
1920
2320
|
}, []);
|
|
1921
|
-
const recoverTechnicalFailure =
|
|
2321
|
+
const recoverTechnicalFailure = useCallback3((err, code, generation) => {
|
|
1922
2322
|
invalidateAttempt(generation);
|
|
1923
2323
|
onTechnicalFailure?.("paypal", err, { code, popupBlocked: isPopupBlockedError(err) });
|
|
1924
2324
|
setShowRecoveryAction(true);
|
|
1925
2325
|
resetSurface();
|
|
1926
2326
|
}, [invalidateAttempt, onTechnicalFailure, resetSurface]);
|
|
1927
|
-
const focusProviderSurface =
|
|
2327
|
+
const focusProviderSurface = useCallback3(() => {
|
|
1928
2328
|
window.setTimeout(() => {
|
|
1929
2329
|
const target = focusTargetRef.current?.querySelector("iframe");
|
|
1930
2330
|
(target ?? focusTargetRef.current)?.focus();
|
|
@@ -1935,7 +2335,7 @@ function PayPalButtonInner({
|
|
|
1935
2335
|
pendingProviderFocusRef.current = false;
|
|
1936
2336
|
focusProviderSurface();
|
|
1937
2337
|
}, [focusProviderSurface, surfaceKey]);
|
|
1938
|
-
const handleRecoveryActionClick =
|
|
2338
|
+
const handleRecoveryActionClick = useCallback3(() => {
|
|
1939
2339
|
setShowRecoveryAction(false);
|
|
1940
2340
|
onErrorChange?.(null);
|
|
1941
2341
|
focusProviderSurface();
|
|
@@ -2006,7 +2406,7 @@ function PayPalButtonInner({
|
|
|
2006
2406
|
}
|
|
2007
2407
|
})();
|
|
2008
2408
|
}, [stripe, onTokenizedBody, onErrorChange, onDecline]);
|
|
2009
|
-
const handlePayPalClick =
|
|
2409
|
+
const handlePayPalClick = useCallback3(async (event) => {
|
|
2010
2410
|
if (isProcessing || submitting) {
|
|
2011
2411
|
event.reject();
|
|
2012
2412
|
return;
|
|
@@ -2028,7 +2428,7 @@ function PayPalButtonInner({
|
|
|
2028
2428
|
onButtonClick?.("paypal");
|
|
2029
2429
|
event.resolve();
|
|
2030
2430
|
}, [attemptContextBySurfaceRef, isProcessing, onButtonClick, runBeforeButtonClick, startAttempt, submitting, surfaceKey]);
|
|
2031
|
-
const handlePayPalConfirm =
|
|
2431
|
+
const handlePayPalConfirm = useCallback3(async (event) => {
|
|
2032
2432
|
if (!stripe || !elements) return;
|
|
2033
2433
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
2034
2434
|
if (attemptContext && !isAttemptCurrent(attemptContext.generation)) {
|
|
@@ -2068,8 +2468,7 @@ function PayPalButtonInner({
|
|
|
2068
2468
|
event.paymentFailed({ reason: "fail" });
|
|
2069
2469
|
return;
|
|
2070
2470
|
}
|
|
2071
|
-
const intentHeaders =
|
|
2072
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
2471
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2073
2472
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2074
2473
|
method: "POST",
|
|
2075
2474
|
headers: intentHeaders,
|
|
@@ -2160,14 +2559,14 @@ function PayPalButtonInner({
|
|
|
2160
2559
|
setSubmitting(false);
|
|
2161
2560
|
}
|
|
2162
2561
|
}, [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick, recoverTechnicalFailure, finishAttempt, isAttemptCurrent, isAttemptInvalidated, surfaceKey]);
|
|
2163
|
-
return /* @__PURE__ */
|
|
2164
|
-
/* @__PURE__ */
|
|
2562
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2563
|
+
/* @__PURE__ */ jsx8(
|
|
2165
2564
|
ExpressCheckoutReadySwap,
|
|
2166
2565
|
{
|
|
2167
2566
|
state: loadState,
|
|
2168
2567
|
placeholderTestId: "flopay-paypal-placeholder",
|
|
2169
2568
|
borderRadius: placeholderBorderRadius,
|
|
2170
|
-
children: /* @__PURE__ */
|
|
2569
|
+
children: /* @__PURE__ */ jsxs5(
|
|
2171
2570
|
"div",
|
|
2172
2571
|
{
|
|
2173
2572
|
ref: focusTargetRef,
|
|
@@ -2176,7 +2575,7 @@ function PayPalButtonInner({
|
|
|
2176
2575
|
"aria-label": "PayPal payment method",
|
|
2177
2576
|
style: { borderRadius: 8, outlineOffset: 4 },
|
|
2178
2577
|
children: [
|
|
2179
|
-
showRecoveryAction && /* @__PURE__ */
|
|
2578
|
+
showRecoveryAction && /* @__PURE__ */ jsx8(
|
|
2180
2579
|
"button",
|
|
2181
2580
|
{
|
|
2182
2581
|
ref: recoveryActionRef,
|
|
@@ -2187,7 +2586,7 @@ function PayPalButtonInner({
|
|
|
2187
2586
|
children: "Try PayPal again"
|
|
2188
2587
|
}
|
|
2189
2588
|
),
|
|
2190
|
-
/* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ jsx8(
|
|
2191
2590
|
ExpressCheckoutElement,
|
|
2192
2591
|
{
|
|
2193
2592
|
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
@@ -2197,6 +2596,11 @@ function PayPalButtonInner({
|
|
|
2197
2596
|
onCancel: () => {
|
|
2198
2597
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
2199
2598
|
attemptContextBySurfaceRef.current.delete(surfaceKey);
|
|
2599
|
+
getFloPayTelemetryBridge(flopay)?.terminal({
|
|
2600
|
+
outcome: "payment_cancelled",
|
|
2601
|
+
provider: "paypal",
|
|
2602
|
+
paymentMethodCategory: "paypal"
|
|
2603
|
+
});
|
|
2200
2604
|
invalidateAttempt(attemptContext?.generation);
|
|
2201
2605
|
setShowRecoveryAction(false);
|
|
2202
2606
|
pendingProviderFocusRef.current = true;
|
|
@@ -2222,7 +2626,7 @@ function PayPalButtonInner({
|
|
|
2222
2626
|
)
|
|
2223
2627
|
}
|
|
2224
2628
|
),
|
|
2225
|
-
submitting && /* @__PURE__ */
|
|
2629
|
+
submitting && /* @__PURE__ */ jsx8(ProcessingOverlay, { status: "processing" })
|
|
2226
2630
|
] });
|
|
2227
2631
|
}
|
|
2228
2632
|
function WalletButtonInner({
|
|
@@ -2240,6 +2644,7 @@ function WalletButtonInner({
|
|
|
2240
2644
|
onLoadStateChange,
|
|
2241
2645
|
placeholderBorderRadius
|
|
2242
2646
|
}) {
|
|
2647
|
+
const flopay = useFloPay();
|
|
2243
2648
|
const stripe = useStripeRaw();
|
|
2244
2649
|
const elements = useStripeElements();
|
|
2245
2650
|
const [loadState, setLoadState] = useState3("loading");
|
|
@@ -2248,15 +2653,15 @@ function WalletButtonInner({
|
|
|
2248
2653
|
}, [loadState, onLoadStateChange]);
|
|
2249
2654
|
const [submitting, setSubmitting] = useState3(false);
|
|
2250
2655
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2251
|
-
const focusTargetRef =
|
|
2252
|
-
const recoveryActionRef =
|
|
2656
|
+
const focusTargetRef = useRef5(null);
|
|
2657
|
+
const recoveryActionRef = useRef5(null);
|
|
2253
2658
|
const [surfaceKey, setSurfaceKey] = useState3(0);
|
|
2254
2659
|
const [showRecoveryAction, setShowRecoveryAction] = useState3(false);
|
|
2255
2660
|
const [recoveryActionMethod, setRecoveryActionMethod] = useState3("google_pay");
|
|
2256
|
-
const pendingProviderFocusRef =
|
|
2257
|
-
const lastWalletProviderMethodRef =
|
|
2258
|
-
const lastWalletMethodRef =
|
|
2259
|
-
const attemptContextBySurfaceRef =
|
|
2661
|
+
const pendingProviderFocusRef = useRef5(false);
|
|
2662
|
+
const lastWalletProviderMethodRef = useRef5("google_pay");
|
|
2663
|
+
const lastWalletMethodRef = useRef5("google_pay");
|
|
2664
|
+
const attemptContextBySurfaceRef = useRef5(/* @__PURE__ */ new Map());
|
|
2260
2665
|
const {
|
|
2261
2666
|
startAttempt,
|
|
2262
2667
|
finishAttempt,
|
|
@@ -2275,17 +2680,17 @@ function WalletButtonInner({
|
|
|
2275
2680
|
useEffect5(() => {
|
|
2276
2681
|
if (showRecoveryAction) recoveryActionRef.current?.focus();
|
|
2277
2682
|
}, [showRecoveryAction, surfaceKey]);
|
|
2278
|
-
const resetSurface =
|
|
2683
|
+
const resetSurface = useCallback3(() => {
|
|
2279
2684
|
setSurfaceKey((key) => key + 1);
|
|
2280
2685
|
}, []);
|
|
2281
|
-
const recoverTechnicalFailure =
|
|
2686
|
+
const recoverTechnicalFailure = useCallback3((method, err, code, generation) => {
|
|
2282
2687
|
invalidateAttempt(generation);
|
|
2283
2688
|
onTechnicalFailure?.(method, err, { code, popupBlocked: isPopupBlockedError(err) });
|
|
2284
2689
|
setRecoveryActionMethod(method);
|
|
2285
2690
|
setShowRecoveryAction(true);
|
|
2286
2691
|
resetSurface();
|
|
2287
2692
|
}, [invalidateAttempt, onTechnicalFailure, resetSurface]);
|
|
2288
|
-
const focusProviderSurface =
|
|
2693
|
+
const focusProviderSurface = useCallback3(() => {
|
|
2289
2694
|
window.setTimeout(() => {
|
|
2290
2695
|
const target = focusTargetRef.current?.querySelector("iframe");
|
|
2291
2696
|
(target ?? focusTargetRef.current)?.focus();
|
|
@@ -2296,12 +2701,12 @@ function WalletButtonInner({
|
|
|
2296
2701
|
pendingProviderFocusRef.current = false;
|
|
2297
2702
|
focusProviderSurface();
|
|
2298
2703
|
}, [focusProviderSurface, surfaceKey]);
|
|
2299
|
-
const handleRecoveryActionClick =
|
|
2704
|
+
const handleRecoveryActionClick = useCallback3(() => {
|
|
2300
2705
|
setShowRecoveryAction(false);
|
|
2301
2706
|
onErrorChange?.(null);
|
|
2302
2707
|
focusProviderSurface();
|
|
2303
2708
|
}, [focusProviderSurface, onErrorChange]);
|
|
2304
|
-
const handleWalletConfirm =
|
|
2709
|
+
const handleWalletConfirm = useCallback3(
|
|
2305
2710
|
async (event) => {
|
|
2306
2711
|
if (!stripe || !elements) return;
|
|
2307
2712
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
@@ -2348,8 +2753,7 @@ function WalletButtonInner({
|
|
|
2348
2753
|
if (!effectiveSessionId || !effectiveEmail) {
|
|
2349
2754
|
throw new Error("Missing sessionId or email for wallet payment");
|
|
2350
2755
|
}
|
|
2351
|
-
const intentHeaders =
|
|
2352
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
2756
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2353
2757
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2354
2758
|
method: "POST",
|
|
2355
2759
|
headers: intentHeaders,
|
|
@@ -2422,14 +2826,14 @@ function WalletButtonInner({
|
|
|
2422
2826
|
() => expressMethods.map(stripeExpressMethodToOptionKey),
|
|
2423
2827
|
[expressMethods]
|
|
2424
2828
|
);
|
|
2425
|
-
return /* @__PURE__ */
|
|
2426
|
-
/* @__PURE__ */
|
|
2829
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2830
|
+
/* @__PURE__ */ jsx8(
|
|
2427
2831
|
ExpressCheckoutReadySwap,
|
|
2428
2832
|
{
|
|
2429
2833
|
state: loadState,
|
|
2430
2834
|
placeholderTestId: "flopay-wallet-placeholder",
|
|
2431
2835
|
borderRadius: placeholderBorderRadius,
|
|
2432
|
-
children: /* @__PURE__ */
|
|
2836
|
+
children: /* @__PURE__ */ jsxs5(
|
|
2433
2837
|
"div",
|
|
2434
2838
|
{
|
|
2435
2839
|
ref: focusTargetRef,
|
|
@@ -2438,7 +2842,7 @@ function WalletButtonInner({
|
|
|
2438
2842
|
"aria-label": "Wallet payment methods",
|
|
2439
2843
|
style: { borderRadius: 8, outlineOffset: 4 },
|
|
2440
2844
|
children: [
|
|
2441
|
-
showRecoveryAction && /* @__PURE__ */
|
|
2845
|
+
showRecoveryAction && /* @__PURE__ */ jsxs5(
|
|
2442
2846
|
"button",
|
|
2443
2847
|
{
|
|
2444
2848
|
ref: recoveryActionRef,
|
|
@@ -2453,7 +2857,7 @@ function WalletButtonInner({
|
|
|
2453
2857
|
]
|
|
2454
2858
|
}
|
|
2455
2859
|
),
|
|
2456
|
-
/* @__PURE__ */
|
|
2860
|
+
/* @__PURE__ */ jsx8(
|
|
2457
2861
|
ExpressCheckoutElement,
|
|
2458
2862
|
{
|
|
2459
2863
|
onReady: (event) => {
|
|
@@ -2461,6 +2865,13 @@ function WalletButtonInner({
|
|
|
2461
2865
|
},
|
|
2462
2866
|
onLoadError: (_event) => {
|
|
2463
2867
|
setLoadState("load_error");
|
|
2868
|
+
getFloPayTelemetryBridge(flopay)?.error({
|
|
2869
|
+
errorCode: "PROVIDER_LOAD_FAILED",
|
|
2870
|
+
stage: "provider_load",
|
|
2871
|
+
provider: "stripe",
|
|
2872
|
+
paymentMethodCategory: "wallet",
|
|
2873
|
+
requestCategory: "provider_sdk"
|
|
2874
|
+
});
|
|
2464
2875
|
},
|
|
2465
2876
|
onClick: async (event) => {
|
|
2466
2877
|
lastWalletProviderMethodRef.current = event.expressPaymentType;
|
|
@@ -2487,6 +2898,11 @@ function WalletButtonInner({
|
|
|
2487
2898
|
onCancel: () => {
|
|
2488
2899
|
const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
|
|
2489
2900
|
attemptContextBySurfaceRef.current.delete(surfaceKey);
|
|
2901
|
+
getFloPayTelemetryBridge(flopay)?.terminal({
|
|
2902
|
+
outcome: "payment_cancelled",
|
|
2903
|
+
provider: "stripe",
|
|
2904
|
+
paymentMethodCategory: "wallet"
|
|
2905
|
+
});
|
|
2490
2906
|
invalidateAttempt(attemptContext?.generation);
|
|
2491
2907
|
setShowRecoveryAction(false);
|
|
2492
2908
|
pendingProviderFocusRef.current = true;
|
|
@@ -2505,7 +2921,7 @@ function WalletButtonInner({
|
|
|
2505
2921
|
)
|
|
2506
2922
|
}
|
|
2507
2923
|
),
|
|
2508
|
-
submitting && /* @__PURE__ */
|
|
2924
|
+
submitting && /* @__PURE__ */ jsx8(ProcessingOverlay, { status: "processing" })
|
|
2509
2925
|
] });
|
|
2510
2926
|
}
|
|
2511
2927
|
function StripeMethodButton({
|
|
@@ -2523,10 +2939,11 @@ function StripeMethodButton({
|
|
|
2523
2939
|
fontFamily
|
|
2524
2940
|
}) {
|
|
2525
2941
|
const brand = resolveStripeMethodBrandVariant(method, themeId);
|
|
2942
|
+
const vendoredLogoUrl = PAYMENT_METHOD_LOGO_URLS[method];
|
|
2526
2943
|
const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
|
|
2527
2944
|
const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
|
|
2528
2945
|
const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
|
|
2529
|
-
return /* @__PURE__ */
|
|
2946
|
+
return /* @__PURE__ */ jsx8(
|
|
2530
2947
|
"button",
|
|
2531
2948
|
{
|
|
2532
2949
|
type: "button",
|
|
@@ -2573,9 +2990,9 @@ function StripeMethodButton({
|
|
|
2573
2990
|
// Pulse-skeleton parity with the wallet ECE: no spinner, just the
|
|
2574
2991
|
// status text on top of the pulsing background. Keeps the loading
|
|
2575
2992
|
// affordance shape-equivalent across both kinds of tile.
|
|
2576
|
-
/* @__PURE__ */
|
|
2577
|
-
) : /* @__PURE__ */
|
|
2578
|
-
/* @__PURE__ */
|
|
2993
|
+
/* @__PURE__ */ jsx8("span", { style: { margin: "0 auto" }, children: `Connecting to ${getStripeMethodDisplayName(method)}\u2026` })
|
|
2994
|
+
) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2995
|
+
/* @__PURE__ */ jsxs5(
|
|
2579
2996
|
"span",
|
|
2580
2997
|
{
|
|
2581
2998
|
style: {
|
|
@@ -2588,15 +3005,36 @@ function StripeMethodButton({
|
|
|
2588
3005
|
gap: hasVendoredStripeMethodLogo(method) ? 8 : 0
|
|
2589
3006
|
},
|
|
2590
3007
|
children: [
|
|
2591
|
-
|
|
3008
|
+
vendoredLogoUrl ? (
|
|
3009
|
+
// Vendored brand logo — an <img> asset (not inline SVG) so its
|
|
3010
|
+
// bytes ship as a sibling file, out of the JS bundle. 3:2 box
|
|
3011
|
+
// matching the datatrans logos' 120×80 viewBox; each ships its own
|
|
3012
|
+
// white rounded-rect background so it stays legible on any tile.
|
|
3013
|
+
/* @__PURE__ */ jsx8(
|
|
3014
|
+
"img",
|
|
3015
|
+
{
|
|
3016
|
+
src: vendoredLogoUrl,
|
|
3017
|
+
alt: "",
|
|
3018
|
+
"aria-hidden": "true",
|
|
3019
|
+
loading: "lazy",
|
|
3020
|
+
decoding: "async",
|
|
3021
|
+
width: 30,
|
|
3022
|
+
height: 20,
|
|
3023
|
+
style: {
|
|
3024
|
+
width: 30,
|
|
3025
|
+
height: 20,
|
|
3026
|
+
flexShrink: 0,
|
|
3027
|
+
borderRadius: 3,
|
|
3028
|
+
objectFit: "contain",
|
|
3029
|
+
display: "inline-flex"
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
)
|
|
3033
|
+
) : brand?.logoSvg ? /* @__PURE__ */ jsx8(
|
|
2592
3034
|
"span",
|
|
2593
3035
|
{
|
|
2594
3036
|
"aria-hidden": "true",
|
|
2595
3037
|
style: {
|
|
2596
|
-
// 3:2 box matching the vendored datatrans logos' 120×80
|
|
2597
|
-
// viewBox. Each logo ships with its own white rounded-rect
|
|
2598
|
-
// background baked in, so the mark stays legible on any
|
|
2599
|
-
// brand-coloured tile without an extra chip wrapper here.
|
|
2600
3038
|
width: 30,
|
|
2601
3039
|
height: 20,
|
|
2602
3040
|
flexShrink: 0,
|
|
@@ -2606,12 +3044,12 @@ function StripeMethodButton({
|
|
|
2606
3044
|
},
|
|
2607
3045
|
dangerouslySetInnerHTML: { __html: brand.logoSvg }
|
|
2608
3046
|
}
|
|
2609
|
-
),
|
|
2610
|
-
/* @__PURE__ */
|
|
3047
|
+
) : null,
|
|
3048
|
+
/* @__PURE__ */ jsx8("span", { children: getStripeMethodDisplayName(method) })
|
|
2611
3049
|
]
|
|
2612
3050
|
}
|
|
2613
3051
|
),
|
|
2614
|
-
hasNextStep && /* @__PURE__ */
|
|
3052
|
+
hasNextStep && /* @__PURE__ */ jsx8(
|
|
2615
3053
|
"svg",
|
|
2616
3054
|
{
|
|
2617
3055
|
width: "14",
|
|
@@ -2631,7 +3069,7 @@ function StripeMethodButton({
|
|
|
2631
3069
|
opacity: 0.7
|
|
2632
3070
|
},
|
|
2633
3071
|
"aria-hidden": "true",
|
|
2634
|
-
children: /* @__PURE__ */
|
|
3072
|
+
children: /* @__PURE__ */ jsx8("path", { d: "M9 18l6-6-6-6" })
|
|
2635
3073
|
}
|
|
2636
3074
|
)
|
|
2637
3075
|
] })
|
|
@@ -2657,14 +3095,15 @@ function StripeMethodInlineForm({
|
|
|
2657
3095
|
submitButtonStyle,
|
|
2658
3096
|
errorText
|
|
2659
3097
|
}) {
|
|
3098
|
+
const flopay = useFloPay();
|
|
2660
3099
|
const stripe = useStripeRaw();
|
|
2661
3100
|
const elements = useStripeElements();
|
|
2662
3101
|
const [submitting, setSubmitting] = useState3(false);
|
|
2663
|
-
const submittingRef =
|
|
3102
|
+
const submittingRef = useRef5(false);
|
|
2664
3103
|
const [isMethodComplete, setIsMethodComplete] = useState3(false);
|
|
2665
3104
|
const [loadState, setLoadState] = useState3("loading");
|
|
2666
3105
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2667
|
-
const handlePay =
|
|
3106
|
+
const handlePay = useCallback3(async () => {
|
|
2668
3107
|
if (!stripe || !elements || isProcessing || submittingRef.current || !isMethodComplete) return;
|
|
2669
3108
|
submittingRef.current = true;
|
|
2670
3109
|
setSubmitting(true);
|
|
@@ -2694,8 +3133,7 @@ function StripeMethodInlineForm({
|
|
|
2694
3133
|
if (!effectiveSessionId || !effectiveEmail) {
|
|
2695
3134
|
throw new Error("Missing sessionId or email for payment.");
|
|
2696
3135
|
}
|
|
2697
|
-
const intentHeaders =
|
|
2698
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
3136
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2699
3137
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2700
3138
|
method: "POST",
|
|
2701
3139
|
headers: intentHeaders,
|
|
@@ -2749,9 +3187,8 @@ function StripeMethodInlineForm({
|
|
|
2749
3187
|
onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
|
|
2750
3188
|
return;
|
|
2751
3189
|
}
|
|
2752
|
-
const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
|
|
2753
3190
|
const piStatus = paymentIntent?.status;
|
|
2754
|
-
if (!
|
|
3191
|
+
if (!isSuccessfulPaymentIntentStatus(piStatus)) {
|
|
2755
3192
|
if (typeof window !== "undefined") {
|
|
2756
3193
|
try {
|
|
2757
3194
|
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
@@ -2804,12 +3241,21 @@ function StripeMethodInlineForm({
|
|
|
2804
3241
|
onDecline
|
|
2805
3242
|
]);
|
|
2806
3243
|
void onCancel;
|
|
2807
|
-
return /* @__PURE__ */
|
|
2808
|
-
/* @__PURE__ */
|
|
3244
|
+
return /* @__PURE__ */ jsxs5("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
|
|
3245
|
+
/* @__PURE__ */ jsx8(
|
|
2809
3246
|
PaymentElement2,
|
|
2810
3247
|
{
|
|
2811
3248
|
onReady: () => setLoadState("ready"),
|
|
2812
|
-
onLoadError: () =>
|
|
3249
|
+
onLoadError: () => {
|
|
3250
|
+
setLoadState("load_error");
|
|
3251
|
+
getFloPayTelemetryBridge(flopay)?.error({
|
|
3252
|
+
errorCode: "PROVIDER_LOAD_FAILED",
|
|
3253
|
+
stage: "provider_load",
|
|
3254
|
+
provider: "stripe",
|
|
3255
|
+
paymentMethodCategory: "apm",
|
|
3256
|
+
requestCategory: "provider_sdk"
|
|
3257
|
+
});
|
|
3258
|
+
},
|
|
2813
3259
|
onChange: (event) => {
|
|
2814
3260
|
const evRecord = event;
|
|
2815
3261
|
setIsMethodComplete(!!evRecord.complete);
|
|
@@ -2825,7 +3271,7 @@ function StripeMethodInlineForm({
|
|
|
2825
3271
|
}
|
|
2826
3272
|
}
|
|
2827
3273
|
),
|
|
2828
|
-
/* @__PURE__ */
|
|
3274
|
+
/* @__PURE__ */ jsx8(
|
|
2829
3275
|
"button",
|
|
2830
3276
|
{
|
|
2831
3277
|
type: "button",
|
|
@@ -2852,22 +3298,7 @@ function StripeMethodInlineForm({
|
|
|
2852
3298
|
children: submitting ? "Processing\u2026" : `Pay with ${getStripeMethodDisplayName(method)}`
|
|
2853
3299
|
}
|
|
2854
3300
|
),
|
|
2855
|
-
errorText && /* @__PURE__ */
|
|
2856
|
-
margin: "0.75rem 0 0",
|
|
2857
|
-
padding: "0.625rem 0.875rem",
|
|
2858
|
-
background: "#FEF2F2",
|
|
2859
|
-
border: "1px solid #FECACA",
|
|
2860
|
-
borderRadius: "8px",
|
|
2861
|
-
color: "#991B1B",
|
|
2862
|
-
fontSize: "0.85rem",
|
|
2863
|
-
fontWeight: 600,
|
|
2864
|
-
display: "flex",
|
|
2865
|
-
alignItems: "center",
|
|
2866
|
-
gap: "0.5rem"
|
|
2867
|
-
}, children: [
|
|
2868
|
-
/* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
2869
|
-
errorText
|
|
2870
|
-
] })
|
|
3301
|
+
errorText && /* @__PURE__ */ jsx8(ErrorBanner, { margin: "0.75rem 0 0", children: errorText })
|
|
2871
3302
|
] });
|
|
2872
3303
|
}
|
|
2873
3304
|
function StripePaymentElementInner({
|
|
@@ -2897,7 +3328,7 @@ function StripePaymentElementInner({
|
|
|
2897
3328
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
2898
3329
|
const [expandedMethod, setExpandedMethod] = useState3(null);
|
|
2899
3330
|
const [submittingMethod, setSubmittingMethod] = useState3(null);
|
|
2900
|
-
const submittingRef =
|
|
3331
|
+
const submittingRef = useRef5(false);
|
|
2901
3332
|
useEffect5(() => {
|
|
2902
3333
|
if (paymentElementMethods.length > 0 && stripeInstance) {
|
|
2903
3334
|
onLoadStateChange?.("ready");
|
|
@@ -2905,7 +3336,7 @@ function StripePaymentElementInner({
|
|
|
2905
3336
|
onLoadStateChange?.("loading");
|
|
2906
3337
|
}
|
|
2907
3338
|
}, [paymentElementMethods.length, stripeInstance, onLoadStateChange]);
|
|
2908
|
-
const handleAutoConfirm =
|
|
3339
|
+
const handleAutoConfirm = useCallback3(async (method) => {
|
|
2909
3340
|
if (!stripeInstance) return;
|
|
2910
3341
|
if (submittingRef.current || isProcessing) return;
|
|
2911
3342
|
submittingRef.current = true;
|
|
@@ -2925,8 +3356,7 @@ function StripePaymentElementInner({
|
|
|
2925
3356
|
if (!effectiveSessionId || !effectiveEmail) {
|
|
2926
3357
|
throw new Error("Missing sessionId or email for payment.");
|
|
2927
3358
|
}
|
|
2928
|
-
const intentHeaders =
|
|
2929
|
-
if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
|
|
3359
|
+
const intentHeaders = intentRequestHeaders(effectiveNonce);
|
|
2930
3360
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
2931
3361
|
method: "POST",
|
|
2932
3362
|
headers: intentHeaders,
|
|
@@ -2992,9 +3422,8 @@ function StripePaymentElementInner({
|
|
|
2992
3422
|
onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
|
|
2993
3423
|
return;
|
|
2994
3424
|
}
|
|
2995
|
-
const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
|
|
2996
3425
|
const piStatus = paymentIntent?.status;
|
|
2997
|
-
if (!
|
|
3426
|
+
if (!isSuccessfulPaymentIntentStatus(piStatus)) {
|
|
2998
3427
|
if (typeof window !== "undefined") {
|
|
2999
3428
|
try {
|
|
3000
3429
|
localStorage.removeItem(STRIPE_RESUME_KEY);
|
|
@@ -3046,7 +3475,7 @@ function StripePaymentElementInner({
|
|
|
3046
3475
|
]);
|
|
3047
3476
|
const [localExpandedMethod, setLocalExpandedMethod] = useState3(null);
|
|
3048
3477
|
const activeExpandedMethod = onExpandApm ? expandedApmMethod ?? null : localExpandedMethod;
|
|
3049
|
-
const handleMethodClick =
|
|
3478
|
+
const handleMethodClick = useCallback3((method) => {
|
|
3050
3479
|
if (submittingRef.current || isProcessing) return;
|
|
3051
3480
|
if (activeExpandedMethod && activeExpandedMethod !== method) return;
|
|
3052
3481
|
if (needsStripeMethodExplicitConfirm(method)) {
|
|
@@ -3066,7 +3495,7 @@ function StripePaymentElementInner({
|
|
|
3066
3495
|
paymentMethodTypes: [localExpandedMethod]
|
|
3067
3496
|
};
|
|
3068
3497
|
}, [localExpandedMethod, paymentElementBaseOptions]);
|
|
3069
|
-
return /* @__PURE__ */
|
|
3498
|
+
return /* @__PURE__ */ jsx8(
|
|
3070
3499
|
"div",
|
|
3071
3500
|
{
|
|
3072
3501
|
"data-testid": "flopay-stripe-payment-element-region",
|
|
@@ -3075,8 +3504,8 @@ function StripePaymentElementInner({
|
|
|
3075
3504
|
const isExpanded = expandedApmMethod === method;
|
|
3076
3505
|
const isSubmittingThis = submittingMethod === method;
|
|
3077
3506
|
const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
|
|
3078
|
-
return /* @__PURE__ */
|
|
3079
|
-
/* @__PURE__ */
|
|
3507
|
+
return /* @__PURE__ */ jsxs5(React8.Fragment, { children: [
|
|
3508
|
+
/* @__PURE__ */ jsx8(
|
|
3080
3509
|
StripeMethodButton,
|
|
3081
3510
|
{
|
|
3082
3511
|
method,
|
|
@@ -3093,12 +3522,12 @@ function StripePaymentElementInner({
|
|
|
3093
3522
|
fontFamily: buttonAppearance?.fontFamily
|
|
3094
3523
|
}
|
|
3095
3524
|
),
|
|
3096
|
-
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */
|
|
3525
|
+
!onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ jsx8(
|
|
3097
3526
|
StripeElements,
|
|
3098
3527
|
{
|
|
3099
3528
|
stripe: stripeInstance,
|
|
3100
3529
|
options: localInlineElementsOptions,
|
|
3101
|
-
children: /* @__PURE__ */
|
|
3530
|
+
children: /* @__PURE__ */ jsx8(
|
|
3102
3531
|
StripeMethodInlineForm,
|
|
3103
3532
|
{
|
|
3104
3533
|
method,
|
|
@@ -3204,12 +3633,12 @@ function SplitCardFormInner({
|
|
|
3204
3633
|
const [city, setCity] = useState3(cityProp ?? "");
|
|
3205
3634
|
const [stateValue, setStateValue] = useState3(stateProp ?? "");
|
|
3206
3635
|
const [accountPatch, setAccountPatch] = useState3({});
|
|
3207
|
-
const zipCodeRef =
|
|
3208
|
-
const selectedCountryRef =
|
|
3209
|
-
const addressLine1Ref =
|
|
3210
|
-
const addressLine2Ref =
|
|
3211
|
-
const cityRef =
|
|
3212
|
-
const stateRef =
|
|
3636
|
+
const zipCodeRef = useRef5(zipProp ?? "");
|
|
3637
|
+
const selectedCountryRef = useRef5(countryProp ?? "US");
|
|
3638
|
+
const addressLine1Ref = useRef5(addressLine1Prop ?? "");
|
|
3639
|
+
const addressLine2Ref = useRef5(addressLine2Prop ?? "");
|
|
3640
|
+
const cityRef = useRef5(cityProp ?? "");
|
|
3641
|
+
const stateRef = useRef5(stateProp ?? "");
|
|
3213
3642
|
const avsConfig = useMemo3(() => resolveAVSConfig(enableAVSProp), [enableAVSProp]);
|
|
3214
3643
|
const enableAVS = avsConfig !== null;
|
|
3215
3644
|
const vaultBlockReady = Boolean(session?.vault?.html);
|
|
@@ -3251,20 +3680,20 @@ function SplitCardFormInner({
|
|
|
3251
3680
|
const [expandedApmMethod, setExpandedApmMethod] = useState3(null);
|
|
3252
3681
|
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
3253
3682
|
const TRANSITION_MS = 280;
|
|
3254
|
-
const expandToCard =
|
|
3683
|
+
const expandToCard = useCallback3(() => {
|
|
3255
3684
|
setViewState("expanding");
|
|
3256
3685
|
setTimeout(() => setViewState("card"), TRANSITION_MS);
|
|
3257
3686
|
}, []);
|
|
3258
|
-
const collapseToButtons =
|
|
3687
|
+
const collapseToButtons = useCallback3(() => {
|
|
3259
3688
|
setViewState("collapsing");
|
|
3260
3689
|
setTimeout(() => setViewState("buttons"), TRANSITION_MS);
|
|
3261
3690
|
}, []);
|
|
3262
|
-
const expandToApm =
|
|
3691
|
+
const expandToApm = useCallback3((method) => {
|
|
3263
3692
|
setExpandedApmMethod(method);
|
|
3264
3693
|
setViewState("apm-expanding");
|
|
3265
3694
|
setTimeout(() => setViewState("apm-form"), TRANSITION_MS);
|
|
3266
3695
|
}, []);
|
|
3267
|
-
const collapseFromApm =
|
|
3696
|
+
const collapseFromApm = useCallback3(() => {
|
|
3268
3697
|
setViewState("apm-collapsing");
|
|
3269
3698
|
setTimeout(() => {
|
|
3270
3699
|
setViewState("buttons");
|
|
@@ -3279,9 +3708,9 @@ function SplitCardFormInner({
|
|
|
3279
3708
|
const [fullName, setFullName] = useState3("");
|
|
3280
3709
|
const [formReady, setFormReady] = useState3(false);
|
|
3281
3710
|
const [overlayStatus, setOverlayStatus] = useState3(null);
|
|
3282
|
-
const processingRef =
|
|
3711
|
+
const processingRef = useRef5(false);
|
|
3283
3712
|
const [paypalDirectRetry, setPaypalDirectRetry] = useState3(null);
|
|
3284
|
-
const paypalDirectRetryRef =
|
|
3713
|
+
const paypalDirectRetryRef = useRef5(paypalDirectRetry);
|
|
3285
3714
|
useEffect5(() => {
|
|
3286
3715
|
paypalDirectRetryRef.current = paypalDirectRetry;
|
|
3287
3716
|
}, [paypalDirectRetry]);
|
|
@@ -3389,7 +3818,7 @@ function SplitCardFormInner({
|
|
|
3389
3818
|
setupFutureUsage: "off_session",
|
|
3390
3819
|
...stripeAppearanceProp
|
|
3391
3820
|
}), [amountInCents, currency, stripeAppearanceProp]);
|
|
3392
|
-
const updateError =
|
|
3821
|
+
const updateError = useCallback3(
|
|
3393
3822
|
(err) => {
|
|
3394
3823
|
setError(err);
|
|
3395
3824
|
onErrorChange?.(err);
|
|
@@ -3405,13 +3834,13 @@ function SplitCardFormInner({
|
|
|
3405
3834
|
updateError(null);
|
|
3406
3835
|
}
|
|
3407
3836
|
}, [viewState, updateError]);
|
|
3408
|
-
const emitDecline =
|
|
3837
|
+
const emitDecline = useCallback3(
|
|
3409
3838
|
(method, input, overrides) => {
|
|
3410
3839
|
onDecline?.(buildDeclineEvent(method, input, overrides));
|
|
3411
3840
|
},
|
|
3412
3841
|
[onDecline]
|
|
3413
3842
|
);
|
|
3414
|
-
const recoverExternalMethodTechnicalFailure =
|
|
3843
|
+
const recoverExternalMethodTechnicalFailure = useCallback3(
|
|
3415
3844
|
(method, err, options) => {
|
|
3416
3845
|
const popupBlocked = options?.popupBlocked ?? isPopupBlockedError(err);
|
|
3417
3846
|
const message = buildExternalMethodRecoveryMessage(method, popupBlocked);
|
|
@@ -3473,7 +3902,7 @@ function SplitCardFormInner({
|
|
|
3473
3902
|
nonce,
|
|
3474
3903
|
updateError
|
|
3475
3904
|
]);
|
|
3476
|
-
const vaultOutcomeRef =
|
|
3905
|
+
const vaultOutcomeRef = useRef5({
|
|
3477
3906
|
onComplete,
|
|
3478
3907
|
onError,
|
|
3479
3908
|
updateError,
|
|
@@ -3499,8 +3928,8 @@ function SplitCardFormInner({
|
|
|
3499
3928
|
nonce,
|
|
3500
3929
|
baseUrl
|
|
3501
3930
|
};
|
|
3502
|
-
const vaultCompletedRef =
|
|
3503
|
-
const buildVaultAccountSnapshot =
|
|
3931
|
+
const vaultCompletedRef = useRef5(false);
|
|
3932
|
+
const buildVaultAccountSnapshot = useCallback3(() => {
|
|
3504
3933
|
const { resolvedAccount: resolvedAccount2, avsConfig: avsConfig2, fullName: fullName2, avsCheckProp: avsCheckProp2 } = vaultOutcomeRef.current;
|
|
3505
3934
|
const cc = selectedCountryRef.current || resolvedAccount2.country || "US";
|
|
3506
3935
|
const stateVisible = avsConfig2 ? isAVSFieldVisible(avsConfig2.state, cc) : false;
|
|
@@ -3656,7 +4085,7 @@ function SplitCardFormInner({
|
|
|
3656
4085
|
const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
|
|
3657
4086
|
const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
|
|
3658
4087
|
const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
|
|
3659
|
-
const validationFiredRef =
|
|
4088
|
+
const validationFiredRef = useRef5(false);
|
|
3660
4089
|
useEffect5(() => {
|
|
3661
4090
|
if (validationFiredRef.current) return;
|
|
3662
4091
|
if (!showStripe && !showPayPal) {
|
|
@@ -3677,7 +4106,7 @@ function SplitCardFormInner({
|
|
|
3677
4106
|
updateError(err.message);
|
|
3678
4107
|
}
|
|
3679
4108
|
}, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
|
|
3680
|
-
const deprecationLoggedRef =
|
|
4109
|
+
const deprecationLoggedRef = useRef5(false);
|
|
3681
4110
|
useEffect5(() => {
|
|
3682
4111
|
if (deprecationLoggedRef.current) return;
|
|
3683
4112
|
if (!hasEnabledMethods) return;
|
|
@@ -3690,14 +4119,14 @@ function SplitCardFormInner({
|
|
|
3690
4119
|
`[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.`
|
|
3691
4120
|
);
|
|
3692
4121
|
}, [hasEnabledMethods, showApplePay, showGooglePay]);
|
|
3693
|
-
const handleNameChange =
|
|
4122
|
+
const handleNameChange = useCallback3((value) => {
|
|
3694
4123
|
setFullName(value);
|
|
3695
4124
|
onFullNameChange?.(value);
|
|
3696
4125
|
const parts = value.trim().split(/\s+/);
|
|
3697
4126
|
onFirstNameChange?.(parts[0] ?? "");
|
|
3698
4127
|
onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
|
|
3699
4128
|
}, [onFullNameChange, onFirstNameChange, onLastNameChange]);
|
|
3700
|
-
const applyInlineSessionPatch =
|
|
4129
|
+
const applyInlineSessionPatch = useCallback3(
|
|
3701
4130
|
(patch, method) => {
|
|
3702
4131
|
if (!checkout.applyInlineSessionPatch) {
|
|
3703
4132
|
return Promise.resolve({ error: null, sessionId, nonce });
|
|
@@ -3719,7 +4148,7 @@ function SplitCardFormInner({
|
|
|
3719
4148
|
},
|
|
3720
4149
|
[checkout.applyInlineSessionPatch, nonce, onError, sessionId, updateError]
|
|
3721
4150
|
);
|
|
3722
|
-
const runBeforeButtonClick =
|
|
4151
|
+
const runBeforeButtonClick = useCallback3(async (method) => {
|
|
3723
4152
|
if (!onBeforeButtonClick) return { proceed: true };
|
|
3724
4153
|
try {
|
|
3725
4154
|
const result = await onBeforeButtonClick({
|
|
@@ -3756,7 +4185,7 @@ function SplitCardFormInner({
|
|
|
3756
4185
|
return { proceed: false };
|
|
3757
4186
|
}
|
|
3758
4187
|
}, [applyInlineSessionPatch, checkout.inlineSessionDraft, onBeforeButtonClick, onError, sessionId, updateError]);
|
|
3759
|
-
const processPaymentInternal =
|
|
4188
|
+
const processPaymentInternal = useCallback3(
|
|
3760
4189
|
async (tokenizedBody, overrides) => {
|
|
3761
4190
|
if (processingRef.current) return;
|
|
3762
4191
|
processingRef.current = true;
|
|
@@ -3967,7 +4396,7 @@ function SplitCardFormInner({
|
|
|
3967
4396
|
},
|
|
3968
4397
|
[baseUrl, sessionId, nonce, resolvedAccount, fullName, chv, flopay, paypalFlopay, onComplete, onError, updateError, emitDecline]
|
|
3969
4398
|
);
|
|
3970
|
-
const dispatchTokenizedBody =
|
|
4399
|
+
const dispatchTokenizedBody = useCallback3(
|
|
3971
4400
|
(tokenizedBody, overrides) => {
|
|
3972
4401
|
if (onTokenizedBody) {
|
|
3973
4402
|
onTokenizedBody(tokenizedBody);
|
|
@@ -4004,7 +4433,7 @@ function SplitCardFormInner({
|
|
|
4004
4433
|
}
|
|
4005
4434
|
}
|
|
4006
4435
|
}), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
|
|
4007
|
-
const stripeResumeAttemptedRef =
|
|
4436
|
+
const stripeResumeAttemptedRef = useRef5(false);
|
|
4008
4437
|
useEffect5(() => {
|
|
4009
4438
|
if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
|
|
4010
4439
|
const params = new URLSearchParams(window.location.search);
|
|
@@ -4066,7 +4495,7 @@ function SplitCardFormInner({
|
|
|
4066
4495
|
return;
|
|
4067
4496
|
}
|
|
4068
4497
|
const piStatus = paymentIntent?.status;
|
|
4069
|
-
const successful = piStatus
|
|
4498
|
+
const successful = isSuccessfulPaymentIntentStatus(piStatus);
|
|
4070
4499
|
if (!paymentIntent || !successful) {
|
|
4071
4500
|
const message = piStatus === "canceled" ? "Payment was canceled." : "Payment was not completed. Please try again.";
|
|
4072
4501
|
updateError(message);
|
|
@@ -4083,7 +4512,7 @@ function SplitCardFormInner({
|
|
|
4083
4512
|
}, persistedOverrides);
|
|
4084
4513
|
})();
|
|
4085
4514
|
}, [sessionId, dispatchTokenizedBody, flopay, updateError, emitDecline]);
|
|
4086
|
-
const handleSubmit =
|
|
4515
|
+
const handleSubmit = useCallback3(
|
|
4087
4516
|
async (e) => {
|
|
4088
4517
|
e.preventDefault();
|
|
4089
4518
|
if (!flopay || !elements || isSubmitting || processingRef.current) return;
|
|
@@ -4166,8 +4595,7 @@ function SplitCardFormInner({
|
|
|
4166
4595
|
updateError(pmResult.error?.message ?? "Failed to create payment method.");
|
|
4167
4596
|
return;
|
|
4168
4597
|
}
|
|
4169
|
-
const intentHeaders =
|
|
4170
|
-
if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
|
|
4598
|
+
const intentHeaders = intentRequestHeaders(nonce);
|
|
4171
4599
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
4172
4600
|
method: "POST",
|
|
4173
4601
|
headers: intentHeaders,
|
|
@@ -4243,7 +4671,7 @@ function SplitCardFormInner({
|
|
|
4243
4671
|
);
|
|
4244
4672
|
const isReady = flopay !== null && (vaultActive || elements !== null);
|
|
4245
4673
|
if (!isReady) {
|
|
4246
|
-
return /* @__PURE__ */
|
|
4674
|
+
return /* @__PURE__ */ jsx8("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
|
|
4247
4675
|
}
|
|
4248
4676
|
const isButtons = layout === "buttons";
|
|
4249
4677
|
const appearanceVars = appearance?.variables;
|
|
@@ -4302,7 +4730,7 @@ function SplitCardFormInner({
|
|
|
4302
4730
|
const containerOverrides = bStyles.cardFormContainer ?? {};
|
|
4303
4731
|
const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
|
|
4304
4732
|
const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
|
|
4305
|
-
const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */
|
|
4733
|
+
const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ jsx8(
|
|
4306
4734
|
VaultCardFields,
|
|
4307
4735
|
{
|
|
4308
4736
|
capture: cardCapture,
|
|
@@ -4340,7 +4768,7 @@ function SplitCardFormInner({
|
|
|
4340
4768
|
if (message) setOverlayStatus(null);
|
|
4341
4769
|
}
|
|
4342
4770
|
}
|
|
4343
|
-
) : /* @__PURE__ */
|
|
4771
|
+
) : /* @__PURE__ */ jsx8(
|
|
4344
4772
|
"div",
|
|
4345
4773
|
{
|
|
4346
4774
|
"data-testid": "flopay-vault-loading",
|
|
@@ -4355,7 +4783,7 @@ function SplitCardFormInner({
|
|
|
4355
4783
|
children: "Loading secure card form\u2026"
|
|
4356
4784
|
}
|
|
4357
4785
|
);
|
|
4358
|
-
const cardFormBlock = /* @__PURE__ */
|
|
4786
|
+
const cardFormBlock = /* @__PURE__ */ jsxs5("div", { style: {
|
|
4359
4787
|
backgroundColor: cardBg,
|
|
4360
4788
|
borderRadius: containerRadius,
|
|
4361
4789
|
...containerOverrides,
|
|
@@ -4368,7 +4796,7 @@ function SplitCardFormInner({
|
|
|
4368
4796
|
display: "flex",
|
|
4369
4797
|
flexDirection: "column"
|
|
4370
4798
|
}, children: [
|
|
4371
|
-
/* @__PURE__ */
|
|
4799
|
+
/* @__PURE__ */ jsx8("style", { children: `
|
|
4372
4800
|
.flopay-shared-input::placeholder {
|
|
4373
4801
|
color: var(--flopay-input-placeholder-color);
|
|
4374
4802
|
opacity: 1;
|
|
@@ -4377,14 +4805,14 @@ function SplitCardFormInner({
|
|
|
4377
4805
|
font-weight: var(--flopay-input-font-weight);
|
|
4378
4806
|
}
|
|
4379
4807
|
` }),
|
|
4380
|
-
isButtons && showCardForm && /* @__PURE__ */
|
|
4808
|
+
isButtons && showCardForm && /* @__PURE__ */ jsxs5("div", { style: {
|
|
4381
4809
|
display: "flex",
|
|
4382
4810
|
alignItems: "center",
|
|
4383
4811
|
padding: "0.75rem 0 0.625rem",
|
|
4384
4812
|
// Keep the header on top when AVS is ordered above the card on vault.
|
|
4385
4813
|
order: vaultActive ? -2 : 0
|
|
4386
4814
|
}, children: [
|
|
4387
|
-
/* @__PURE__ */
|
|
4815
|
+
/* @__PURE__ */ jsxs5(
|
|
4388
4816
|
"button",
|
|
4389
4817
|
{
|
|
4390
4818
|
type: "button",
|
|
@@ -4406,7 +4834,7 @@ function SplitCardFormInner({
|
|
|
4406
4834
|
},
|
|
4407
4835
|
"aria-label": "Back to payment methods",
|
|
4408
4836
|
children: [
|
|
4409
|
-
/* @__PURE__ */
|
|
4837
|
+
/* @__PURE__ */ jsx8("span", { style: {
|
|
4410
4838
|
display: "inline-flex",
|
|
4411
4839
|
alignItems: "center",
|
|
4412
4840
|
justifyContent: "center",
|
|
@@ -4416,12 +4844,12 @@ function SplitCardFormInner({
|
|
|
4416
4844
|
backgroundColor: "#f3f4f6",
|
|
4417
4845
|
transition: "background-color 0.15s",
|
|
4418
4846
|
...bStyles.backButtonIcon
|
|
4419
|
-
}, children: /* @__PURE__ */
|
|
4420
|
-
/* @__PURE__ */
|
|
4847
|
+
}, children: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
4848
|
+
/* @__PURE__ */ jsx8(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
4421
4849
|
]
|
|
4422
4850
|
}
|
|
4423
4851
|
),
|
|
4424
|
-
hideTitle ? /* @__PURE__ */
|
|
4852
|
+
hideTitle ? /* @__PURE__ */ jsx8("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx8("div", { style: {
|
|
4425
4853
|
flex: 1,
|
|
4426
4854
|
textAlign: "center",
|
|
4427
4855
|
fontWeight: 600,
|
|
@@ -4429,9 +4857,9 @@ function SplitCardFormInner({
|
|
|
4429
4857
|
color: "#262833",
|
|
4430
4858
|
paddingRight: 80,
|
|
4431
4859
|
...bStyles.title
|
|
4432
|
-
}, children: /* @__PURE__ */
|
|
4860
|
+
}, children: /* @__PURE__ */ jsx8(TitleContentSlot, { content: cardTitleContent }) })
|
|
4433
4861
|
] }),
|
|
4434
|
-
!isButtons && !hideTitle && /* @__PURE__ */
|
|
4862
|
+
!isButtons && !hideTitle && /* @__PURE__ */ jsx8("div", { style: {
|
|
4435
4863
|
textAlign: "center",
|
|
4436
4864
|
fontWeight: 600,
|
|
4437
4865
|
fontSize: "1.1rem",
|
|
@@ -4441,17 +4869,17 @@ function SplitCardFormInner({
|
|
|
4441
4869
|
// (-2) and AVS block (-1) are ordered below it but above the card form.
|
|
4442
4870
|
order: vaultActive ? -3 : 0,
|
|
4443
4871
|
...bStyles.title
|
|
4444
|
-
}, children: /* @__PURE__ */
|
|
4445
|
-
!vaultActive && /* @__PURE__ */
|
|
4446
|
-
/* @__PURE__ */
|
|
4872
|
+
}, children: /* @__PURE__ */ jsx8(TitleContentSlot, { content: cardTitleContent }) }),
|
|
4873
|
+
!vaultActive && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
4874
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
4447
4875
|
backgroundColor: cardInputBg,
|
|
4448
4876
|
border: `1px solid ${resolvedBorder}`,
|
|
4449
4877
|
borderTopLeftRadius: resolvedBorderRadius,
|
|
4450
4878
|
borderTopRightRadius: resolvedBorderRadius,
|
|
4451
4879
|
padding: "10px"
|
|
4452
|
-
}, children: /* @__PURE__ */
|
|
4453
|
-
/* @__PURE__ */
|
|
4454
|
-
/* @__PURE__ */
|
|
4880
|
+
}, children: /* @__PURE__ */ jsx8(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
4881
|
+
/* @__PURE__ */ jsxs5("div", { style: { display: "flex" }, children: [
|
|
4882
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
4455
4883
|
flex: 1,
|
|
4456
4884
|
backgroundColor: cardInputBg,
|
|
4457
4885
|
// Longhand only — mixing `border` shorthand with per-side
|
|
@@ -4463,8 +4891,8 @@ function SplitCardFormInner({
|
|
|
4463
4891
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
4464
4892
|
borderBottomLeftRadius: resolvedBorderRadius,
|
|
4465
4893
|
padding: "10px"
|
|
4466
|
-
}, children: /* @__PURE__ */
|
|
4467
|
-
/* @__PURE__ */
|
|
4894
|
+
}, children: /* @__PURE__ */ jsx8(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
4895
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
4468
4896
|
flex: 1,
|
|
4469
4897
|
backgroundColor: cardInputBg,
|
|
4470
4898
|
borderTop: "none",
|
|
@@ -4473,16 +4901,16 @@ function SplitCardFormInner({
|
|
|
4473
4901
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
4474
4902
|
borderBottomRightRadius: resolvedBorderRadius,
|
|
4475
4903
|
padding: "10px"
|
|
4476
|
-
}, children: /* @__PURE__ */
|
|
4904
|
+
}, children: /* @__PURE__ */ jsx8(CardCvcElement, { options: stripeElementStyle }) })
|
|
4477
4905
|
] })
|
|
4478
4906
|
] }),
|
|
4479
|
-
!vaultActive && /* @__PURE__ */
|
|
4907
|
+
!vaultActive && /* @__PURE__ */ jsx8("div", { style: {
|
|
4480
4908
|
backgroundColor: cardInputBg,
|
|
4481
4909
|
border: `1px solid ${resolvedBorder}`,
|
|
4482
4910
|
borderRadius: resolvedBorderRadius,
|
|
4483
4911
|
marginTop: "0.5rem",
|
|
4484
4912
|
padding: "10px"
|
|
4485
|
-
}, children: /* @__PURE__ */
|
|
4913
|
+
}, children: /* @__PURE__ */ jsx8(
|
|
4486
4914
|
"input",
|
|
4487
4915
|
{
|
|
4488
4916
|
className: "flopay-shared-input",
|
|
@@ -4504,7 +4932,7 @@ function SplitCardFormInner({
|
|
|
4504
4932
|
}
|
|
4505
4933
|
}
|
|
4506
4934
|
) }),
|
|
4507
|
-
avsConfig && /* @__PURE__ */
|
|
4935
|
+
avsConfig && /* @__PURE__ */ jsx8("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
|
|
4508
4936
|
const cc = selectedCountry;
|
|
4509
4937
|
const inputWrapStyle = (invalid = false) => ({
|
|
4510
4938
|
backgroundColor: cardInputBg,
|
|
@@ -4521,8 +4949,8 @@ function SplitCardFormInner({
|
|
|
4521
4949
|
...sharedInputTypography
|
|
4522
4950
|
});
|
|
4523
4951
|
const stateOpts = getStateOptions(cc);
|
|
4524
|
-
return /* @__PURE__ */
|
|
4525
|
-
isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */
|
|
4952
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
4953
|
+
isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */ jsx8("div", { style: inputWrapStyle(invalidAvsFields.line1), children: /* @__PURE__ */ jsx8(
|
|
4526
4954
|
"input",
|
|
4527
4955
|
{
|
|
4528
4956
|
className: "flopay-shared-input",
|
|
@@ -4541,7 +4969,7 @@ function SplitCardFormInner({
|
|
|
4541
4969
|
style: inputFieldStyle()
|
|
4542
4970
|
}
|
|
4543
4971
|
) }),
|
|
4544
|
-
isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */
|
|
4972
|
+
isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */ jsx8("div", { style: inputWrapStyle(), children: /* @__PURE__ */ jsx8(
|
|
4545
4973
|
"input",
|
|
4546
4974
|
{
|
|
4547
4975
|
className: "flopay-shared-input",
|
|
@@ -4559,12 +4987,12 @@ function SplitCardFormInner({
|
|
|
4559
4987
|
style: inputFieldStyle()
|
|
4560
4988
|
}
|
|
4561
4989
|
) }),
|
|
4562
|
-
(isAVSFieldVisible(avsConfig.city, cc) || isAVSFieldVisible(avsConfig.state, cc)) && /* @__PURE__ */
|
|
4990
|
+
(isAVSFieldVisible(avsConfig.city, cc) || isAVSFieldVisible(avsConfig.state, cc)) && /* @__PURE__ */ jsxs5("div", { style: {
|
|
4563
4991
|
display: "flex",
|
|
4564
4992
|
gap: "0",
|
|
4565
4993
|
marginTop: "0.5rem"
|
|
4566
4994
|
}, children: [
|
|
4567
|
-
isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */
|
|
4995
|
+
isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */ jsx8("div", { style: {
|
|
4568
4996
|
flex: 1,
|
|
4569
4997
|
backgroundColor: cardInputBg,
|
|
4570
4998
|
borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
|
|
@@ -4575,7 +5003,7 @@ function SplitCardFormInner({
|
|
|
4575
5003
|
borderTopLeftRadius: resolvedBorderRadius,
|
|
4576
5004
|
borderBottomLeftRadius: resolvedBorderRadius,
|
|
4577
5005
|
...isAVSFieldVisible(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
4578
|
-
}, children: /* @__PURE__ */
|
|
5006
|
+
}, children: /* @__PURE__ */ jsx8(
|
|
4579
5007
|
"input",
|
|
4580
5008
|
{
|
|
4581
5009
|
className: "flopay-shared-input",
|
|
@@ -4594,7 +5022,7 @@ function SplitCardFormInner({
|
|
|
4594
5022
|
style: inputFieldStyle()
|
|
4595
5023
|
}
|
|
4596
5024
|
) }),
|
|
4597
|
-
isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */
|
|
5025
|
+
isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */ jsx8("div", { style: {
|
|
4598
5026
|
flex: 1,
|
|
4599
5027
|
backgroundColor: cardInputBg,
|
|
4600
5028
|
border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
|
|
@@ -4602,7 +5030,7 @@ function SplitCardFormInner({
|
|
|
4602
5030
|
borderTopRightRadius: resolvedBorderRadius,
|
|
4603
5031
|
borderBottomRightRadius: resolvedBorderRadius,
|
|
4604
5032
|
...isAVSFieldVisible(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
|
|
4605
|
-
}, children: stateOpts ? /* @__PURE__ */
|
|
5033
|
+
}, children: stateOpts ? /* @__PURE__ */ jsxs5(
|
|
4606
5034
|
"select",
|
|
4607
5035
|
{
|
|
4608
5036
|
id: "flopay-billing-state",
|
|
@@ -4618,11 +5046,11 @@ function SplitCardFormInner({
|
|
|
4618
5046
|
"data-testid": "flopay-state",
|
|
4619
5047
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
4620
5048
|
children: [
|
|
4621
|
-
/* @__PURE__ */
|
|
4622
|
-
stateOpts.map((s) => /* @__PURE__ */
|
|
5049
|
+
/* @__PURE__ */ jsx8("option", { value: "", children: getStateLabel(cc) }),
|
|
5050
|
+
stateOpts.map((s) => /* @__PURE__ */ jsx8("option", { value: s.code, children: s.name }, s.code))
|
|
4623
5051
|
]
|
|
4624
5052
|
}
|
|
4625
|
-
) : /* @__PURE__ */
|
|
5053
|
+
) : /* @__PURE__ */ jsx8(
|
|
4626
5054
|
"input",
|
|
4627
5055
|
{
|
|
4628
5056
|
className: "flopay-shared-input",
|
|
@@ -4642,13 +5070,13 @@ function SplitCardFormInner({
|
|
|
4642
5070
|
}
|
|
4643
5071
|
) })
|
|
4644
5072
|
] }),
|
|
4645
|
-
(isAVSFieldVisible(avsConfig.country, cc) || isAVSFieldVisible(avsConfig.postal_code, cc)) && /* @__PURE__ */
|
|
5073
|
+
(isAVSFieldVisible(avsConfig.country, cc) || isAVSFieldVisible(avsConfig.postal_code, cc)) && /* @__PURE__ */ jsxs5("div", { style: {
|
|
4646
5074
|
display: "flex",
|
|
4647
5075
|
flexDirection: avsLayoutProp === "column" ? "column" : "row",
|
|
4648
5076
|
gap: avsLayoutProp === "column" ? "0.5rem" : "0",
|
|
4649
5077
|
marginTop: "0.5rem"
|
|
4650
5078
|
}, children: [
|
|
4651
|
-
isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */
|
|
5079
|
+
isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */ jsx8("div", { style: {
|
|
4652
5080
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
4653
5081
|
backgroundColor: cardInputBg,
|
|
4654
5082
|
borderTop: `1px solid ${resolvedBorder}`,
|
|
@@ -4657,7 +5085,7 @@ function SplitCardFormInner({
|
|
|
4657
5085
|
borderLeft: `1px solid ${resolvedBorder}`,
|
|
4658
5086
|
padding: "10px",
|
|
4659
5087
|
...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
|
|
4660
|
-
}, children: /* @__PURE__ */
|
|
5088
|
+
}, children: /* @__PURE__ */ jsx8(
|
|
4661
5089
|
"select",
|
|
4662
5090
|
{
|
|
4663
5091
|
id: "flopay-billing-country",
|
|
@@ -4674,20 +5102,20 @@ function SplitCardFormInner({
|
|
|
4674
5102
|
autoComplete: "billing country",
|
|
4675
5103
|
"data-testid": "flopay-country",
|
|
4676
5104
|
style: { ...inputFieldStyle(), cursor: "pointer" },
|
|
4677
|
-
children: COUNTRY_OPTIONS.map((c) => /* @__PURE__ */
|
|
5105
|
+
children: COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ jsxs5("option", { value: c.code, children: [
|
|
4678
5106
|
c.flag,
|
|
4679
5107
|
" ",
|
|
4680
5108
|
c.name
|
|
4681
5109
|
] }, c.code))
|
|
4682
5110
|
}
|
|
4683
5111
|
) }),
|
|
4684
|
-
isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */
|
|
5112
|
+
isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */ jsx8("div", { style: {
|
|
4685
5113
|
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
4686
5114
|
backgroundColor: cardInputBg,
|
|
4687
5115
|
border: `1px solid ${zipBorderColor}`,
|
|
4688
5116
|
padding: "10px",
|
|
4689
5117
|
...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
|
|
4690
|
-
}, children: /* @__PURE__ */
|
|
5118
|
+
}, children: /* @__PURE__ */ jsx8(
|
|
4691
5119
|
"input",
|
|
4692
5120
|
{
|
|
4693
5121
|
className: "flopay-shared-input",
|
|
@@ -4711,7 +5139,7 @@ function SplitCardFormInner({
|
|
|
4711
5139
|
}
|
|
4712
5140
|
) })
|
|
4713
5141
|
] }),
|
|
4714
|
-
showPostcodeError && /* @__PURE__ */
|
|
5142
|
+
showPostcodeError && /* @__PURE__ */ jsx8(
|
|
4715
5143
|
"div",
|
|
4716
5144
|
{
|
|
4717
5145
|
id: "flopay-billing-postal-code-error",
|
|
@@ -4728,26 +5156,10 @@ function SplitCardFormInner({
|
|
|
4728
5156
|
)
|
|
4729
5157
|
] });
|
|
4730
5158
|
})() }),
|
|
4731
|
-
vaultActive && cardPreFormSlot && /* @__PURE__ */
|
|
5159
|
+
vaultActive && cardPreFormSlot && /* @__PURE__ */ jsx8("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
|
|
4732
5160
|
vaultActive && vaultCardFieldsNode,
|
|
4733
|
-
displayError && /* @__PURE__ */
|
|
4734
|
-
|
|
4735
|
-
padding: "0.625rem 0.875rem",
|
|
4736
|
-
background: "#FEF2F2",
|
|
4737
|
-
border: "1px solid #FECACA",
|
|
4738
|
-
borderRadius: "8px",
|
|
4739
|
-
color: "#991B1B",
|
|
4740
|
-
fontSize: "0.85rem",
|
|
4741
|
-
fontWeight: 600,
|
|
4742
|
-
display: "flex",
|
|
4743
|
-
alignItems: "center",
|
|
4744
|
-
gap: "0.5rem",
|
|
4745
|
-
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
4746
|
-
}, children: [
|
|
4747
|
-
/* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
4748
|
-
displayError
|
|
4749
|
-
] }),
|
|
4750
|
-
!vaultActive && (children ?? /* @__PURE__ */ jsx7(
|
|
5161
|
+
displayError && /* @__PURE__ */ jsx8(ErrorBanner, { margin: "0.75rem 0", styleOverride: bStyles.errorBanner, children: displayError }),
|
|
5162
|
+
!vaultActive && (children ?? /* @__PURE__ */ jsx8(
|
|
4751
5163
|
"button",
|
|
4752
5164
|
{
|
|
4753
5165
|
type: "submit",
|
|
@@ -4792,9 +5204,9 @@ function SplitCardFormInner({
|
|
|
4792
5204
|
const renderDirectPaypalGateDebug = (testId) => {
|
|
4793
5205
|
if (!debug) return null;
|
|
4794
5206
|
if (!showPayPal || !directPaypalConfigured) {
|
|
4795
|
-
return /* @__PURE__ */
|
|
5207
|
+
return /* @__PURE__ */ jsx8("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
|
|
4796
5208
|
}
|
|
4797
|
-
return /* @__PURE__ */
|
|
5209
|
+
return /* @__PURE__ */ jsx8("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
4798
5210
|
"FloPay/DirectPayPal-debug (parent gate)",
|
|
4799
5211
|
` showPayPal=${showPayPal}`,
|
|
4800
5212
|
` directPaypalConfigured=${directPaypalConfigured}`,
|
|
@@ -4807,9 +5219,9 @@ function SplitCardFormInner({
|
|
|
4807
5219
|
const renderStripeGateDebug = (testId) => {
|
|
4808
5220
|
if (!debug) return null;
|
|
4809
5221
|
if (!showStripe || !stripeInstance) {
|
|
4810
|
-
return /* @__PURE__ */
|
|
5222
|
+
return /* @__PURE__ */ jsx8("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
|
|
4811
5223
|
}
|
|
4812
|
-
return /* @__PURE__ */
|
|
5224
|
+
return /* @__PURE__ */ jsx8("pre", { "data-testid": testId, style: gateDebugStyle, children: [
|
|
4813
5225
|
"FloPay/Stripe-debug (parent gate)",
|
|
4814
5226
|
` showStripe=${showStripe}`,
|
|
4815
5227
|
` currency=${currency}`,
|
|
@@ -4838,11 +5250,11 @@ function SplitCardFormInner({
|
|
|
4838
5250
|
const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
4839
5251
|
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;
|
|
4840
5252
|
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;
|
|
4841
|
-
return /* @__PURE__ */
|
|
4842
|
-
/* @__PURE__ */
|
|
4843
|
-
overlayStatus && /* @__PURE__ */
|
|
4844
|
-
/* @__PURE__ */
|
|
4845
|
-
/* @__PURE__ */
|
|
5253
|
+
return /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
5254
|
+
/* @__PURE__ */ jsx8(FloPayKeyframes, {}),
|
|
5255
|
+
overlayStatus && /* @__PURE__ */ jsx8(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
5256
|
+
/* @__PURE__ */ jsxs5("div", { style: { display: "grid" }, children: [
|
|
5257
|
+
/* @__PURE__ */ jsxs5(
|
|
4846
5258
|
"div",
|
|
4847
5259
|
{
|
|
4848
5260
|
"data-testid": "flopay-buttons-panel",
|
|
@@ -4859,8 +5271,8 @@ function SplitCardFormInner({
|
|
|
4859
5271
|
children: [
|
|
4860
5272
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
|
|
4861
5273
|
renderStripeGateDebug("flopay-stripe-gate-debug"),
|
|
4862
|
-
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */
|
|
4863
|
-
paypalDirectRetry && /* @__PURE__ */
|
|
5274
|
+
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
5275
|
+
paypalDirectRetry && /* @__PURE__ */ jsx8(
|
|
4864
5276
|
"div",
|
|
4865
5277
|
{
|
|
4866
5278
|
"data-testid": "flopay-paypal-direct-retry-notice",
|
|
@@ -4876,7 +5288,7 @@ function SplitCardFormInner({
|
|
|
4876
5288
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
4877
5289
|
}
|
|
4878
5290
|
),
|
|
4879
|
-
/* @__PURE__ */
|
|
5291
|
+
/* @__PURE__ */ jsx8(
|
|
4880
5292
|
DirectPayPalButton,
|
|
4881
5293
|
{
|
|
4882
5294
|
sessionId,
|
|
@@ -4903,7 +5315,7 @@ function SplitCardFormInner({
|
|
|
4903
5315
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
4904
5316
|
)
|
|
4905
5317
|
] }),
|
|
4906
|
-
shouldRenderStripePayPal && /* @__PURE__ */
|
|
5318
|
+
shouldRenderStripePayPal && /* @__PURE__ */ jsx8(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx8(
|
|
4907
5319
|
PayPalButtonInner,
|
|
4908
5320
|
{
|
|
4909
5321
|
sessionId,
|
|
@@ -4921,7 +5333,7 @@ function SplitCardFormInner({
|
|
|
4921
5333
|
placeholderBorderRadius: buttonBorderRadius
|
|
4922
5334
|
}
|
|
4923
5335
|
) }),
|
|
4924
|
-
shouldRenderWallets ? /* @__PURE__ */
|
|
5336
|
+
shouldRenderWallets ? /* @__PURE__ */ jsx8(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx8(
|
|
4925
5337
|
WalletButtonInner,
|
|
4926
5338
|
{
|
|
4927
5339
|
sessionId,
|
|
@@ -4938,8 +5350,8 @@ function SplitCardFormInner({
|
|
|
4938
5350
|
onLoadStateChange: setWalletLoadState,
|
|
4939
5351
|
placeholderBorderRadius: buttonBorderRadius
|
|
4940
5352
|
}
|
|
4941
|
-
) }) : shouldShowWallets ? /* @__PURE__ */
|
|
4942
|
-
shouldRenderPaymentElement && /* @__PURE__ */
|
|
5353
|
+
) }) : shouldShowWallets ? /* @__PURE__ */ jsx8("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: buttonBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
5354
|
+
shouldRenderPaymentElement && /* @__PURE__ */ jsx8(
|
|
4943
5355
|
StripePaymentElementInner,
|
|
4944
5356
|
{
|
|
4945
5357
|
sessionId,
|
|
@@ -4971,7 +5383,7 @@ function SplitCardFormInner({
|
|
|
4971
5383
|
}
|
|
4972
5384
|
}
|
|
4973
5385
|
),
|
|
4974
|
-
showStripe && /* @__PURE__ */
|
|
5386
|
+
showStripe && /* @__PURE__ */ jsx8(
|
|
4975
5387
|
"button",
|
|
4976
5388
|
{
|
|
4977
5389
|
type: "button",
|
|
@@ -5027,50 +5439,34 @@ function SplitCardFormInner({
|
|
|
5027
5439
|
onMouseUp: (e) => {
|
|
5028
5440
|
e.currentTarget.style.transform = "scale(1)";
|
|
5029
5441
|
},
|
|
5030
|
-
children: /* @__PURE__ */
|
|
5442
|
+
children: /* @__PURE__ */ jsx8(CardButtonContentSlot, { content: cardButtonContent })
|
|
5031
5443
|
}
|
|
5032
5444
|
),
|
|
5033
|
-
displayError && viewState === "buttons" && /* @__PURE__ */
|
|
5034
|
-
margin: "0.25rem 0",
|
|
5035
|
-
padding: "0.625rem 0.875rem",
|
|
5036
|
-
background: "#FEF2F2",
|
|
5037
|
-
border: "1px solid #FECACA",
|
|
5038
|
-
borderRadius: "8px",
|
|
5039
|
-
color: "#991B1B",
|
|
5040
|
-
fontSize: "0.85rem",
|
|
5041
|
-
fontWeight: 600,
|
|
5042
|
-
display: "flex",
|
|
5043
|
-
alignItems: "center",
|
|
5044
|
-
gap: "0.5rem",
|
|
5045
|
-
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
5046
|
-
}, children: [
|
|
5047
|
-
/* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
5048
|
-
displayError
|
|
5049
|
-
] })
|
|
5445
|
+
displayError && viewState === "buttons" && /* @__PURE__ */ jsx8(ErrorBanner, { margin: "0.25rem 0", styleOverride: bStyles.errorBanner, children: displayError })
|
|
5050
5446
|
]
|
|
5051
5447
|
}
|
|
5052
5448
|
),
|
|
5053
|
-
showStripe && isCardView && /* @__PURE__ */
|
|
5449
|
+
showStripe && isCardView && /* @__PURE__ */ jsx8("div", { style: {
|
|
5054
5450
|
gridArea: "1 / 1",
|
|
5055
5451
|
...cardAnim ? { animation: cardAnim } : {},
|
|
5056
5452
|
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
5057
5453
|
}, children: cardFormBlock }),
|
|
5058
|
-
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */
|
|
5454
|
+
showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ jsx8("div", { style: {
|
|
5059
5455
|
gridArea: "1 / 1",
|
|
5060
5456
|
...apmAnim ? { animation: apmAnim } : {},
|
|
5061
5457
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
5062
|
-
}, children: /* @__PURE__ */
|
|
5458
|
+
}, children: /* @__PURE__ */ jsxs5("div", { style: {
|
|
5063
5459
|
backgroundColor: cardBg,
|
|
5064
5460
|
borderRadius: containerRadius,
|
|
5065
5461
|
...containerOverrides,
|
|
5066
5462
|
padding: containerPadding
|
|
5067
5463
|
}, children: [
|
|
5068
|
-
/* @__PURE__ */
|
|
5464
|
+
/* @__PURE__ */ jsxs5("div", { style: {
|
|
5069
5465
|
display: "flex",
|
|
5070
5466
|
alignItems: "center",
|
|
5071
5467
|
padding: "0.75rem 0 0.625rem"
|
|
5072
5468
|
}, children: [
|
|
5073
|
-
/* @__PURE__ */
|
|
5469
|
+
/* @__PURE__ */ jsxs5(
|
|
5074
5470
|
"button",
|
|
5075
5471
|
{
|
|
5076
5472
|
type: "button",
|
|
@@ -5093,7 +5489,7 @@ function SplitCardFormInner({
|
|
|
5093
5489
|
},
|
|
5094
5490
|
"aria-label": "Back to payment methods",
|
|
5095
5491
|
children: [
|
|
5096
|
-
/* @__PURE__ */
|
|
5492
|
+
/* @__PURE__ */ jsx8("span", { style: {
|
|
5097
5493
|
display: "inline-flex",
|
|
5098
5494
|
alignItems: "center",
|
|
5099
5495
|
justifyContent: "center",
|
|
@@ -5103,12 +5499,12 @@ function SplitCardFormInner({
|
|
|
5103
5499
|
backgroundColor: "#f3f4f6",
|
|
5104
5500
|
transition: "background-color 0.15s",
|
|
5105
5501
|
...bStyles.backButtonIcon
|
|
5106
|
-
}, children: /* @__PURE__ */
|
|
5107
|
-
/* @__PURE__ */
|
|
5502
|
+
}, children: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
5503
|
+
/* @__PURE__ */ jsx8(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
5108
5504
|
]
|
|
5109
5505
|
}
|
|
5110
5506
|
),
|
|
5111
|
-
/* @__PURE__ */
|
|
5507
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
5112
5508
|
flex: 1,
|
|
5113
5509
|
textAlign: "center",
|
|
5114
5510
|
fontWeight: 600,
|
|
@@ -5118,12 +5514,12 @@ function SplitCardFormInner({
|
|
|
5118
5514
|
...bStyles.title
|
|
5119
5515
|
}, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
|
|
5120
5516
|
] }),
|
|
5121
|
-
/* @__PURE__ */
|
|
5517
|
+
/* @__PURE__ */ jsx8(
|
|
5122
5518
|
StripeElements,
|
|
5123
5519
|
{
|
|
5124
5520
|
stripe: stripeInstance,
|
|
5125
5521
|
options: apmInlineOptions,
|
|
5126
|
-
children: /* @__PURE__ */
|
|
5522
|
+
children: /* @__PURE__ */ jsx8(
|
|
5127
5523
|
StripeMethodInlineForm,
|
|
5128
5524
|
{
|
|
5129
5525
|
method: expandedApmMethod,
|
|
@@ -5153,24 +5549,24 @@ function SplitCardFormInner({
|
|
|
5153
5549
|
] });
|
|
5154
5550
|
}
|
|
5155
5551
|
if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
|
|
5156
|
-
return /* @__PURE__ */
|
|
5157
|
-
/* @__PURE__ */
|
|
5158
|
-
overlayStatus && /* @__PURE__ */
|
|
5159
|
-
/* @__PURE__ */
|
|
5552
|
+
return /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
5553
|
+
/* @__PURE__ */ jsx8(FloPayKeyframes, {}),
|
|
5554
|
+
overlayStatus && /* @__PURE__ */ jsx8(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
5555
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
5160
5556
|
...apmAnim ? { animation: apmAnim } : {},
|
|
5161
5557
|
...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
|
|
5162
|
-
}, children: /* @__PURE__ */
|
|
5558
|
+
}, children: /* @__PURE__ */ jsxs5("div", { style: {
|
|
5163
5559
|
backgroundColor: cardBg,
|
|
5164
5560
|
borderRadius: containerRadius,
|
|
5165
5561
|
...containerOverrides,
|
|
5166
5562
|
padding: containerPadding
|
|
5167
5563
|
}, children: [
|
|
5168
|
-
/* @__PURE__ */
|
|
5564
|
+
/* @__PURE__ */ jsxs5("div", { style: {
|
|
5169
5565
|
display: "flex",
|
|
5170
5566
|
alignItems: "center",
|
|
5171
5567
|
padding: "0.75rem 0 0.625rem"
|
|
5172
5568
|
}, children: [
|
|
5173
|
-
/* @__PURE__ */
|
|
5569
|
+
/* @__PURE__ */ jsxs5(
|
|
5174
5570
|
"button",
|
|
5175
5571
|
{
|
|
5176
5572
|
type: "button",
|
|
@@ -5193,7 +5589,7 @@ function SplitCardFormInner({
|
|
|
5193
5589
|
},
|
|
5194
5590
|
"aria-label": "Back to payment methods",
|
|
5195
5591
|
children: [
|
|
5196
|
-
/* @__PURE__ */
|
|
5592
|
+
/* @__PURE__ */ jsx8("span", { style: {
|
|
5197
5593
|
display: "inline-flex",
|
|
5198
5594
|
alignItems: "center",
|
|
5199
5595
|
justifyContent: "center",
|
|
@@ -5203,12 +5599,12 @@ function SplitCardFormInner({
|
|
|
5203
5599
|
backgroundColor: "#f3f4f6",
|
|
5204
5600
|
transition: "background-color 0.15s",
|
|
5205
5601
|
...bStyles.backButtonIcon
|
|
5206
|
-
}, children: /* @__PURE__ */
|
|
5207
|
-
/* @__PURE__ */
|
|
5602
|
+
}, children: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
5603
|
+
/* @__PURE__ */ jsx8(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
5208
5604
|
]
|
|
5209
5605
|
}
|
|
5210
5606
|
),
|
|
5211
|
-
/* @__PURE__ */
|
|
5607
|
+
/* @__PURE__ */ jsx8("div", { style: {
|
|
5212
5608
|
flex: 1,
|
|
5213
5609
|
textAlign: "center",
|
|
5214
5610
|
fontWeight: 600,
|
|
@@ -5218,12 +5614,12 @@ function SplitCardFormInner({
|
|
|
5218
5614
|
...bStyles.title
|
|
5219
5615
|
}, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
|
|
5220
5616
|
] }),
|
|
5221
|
-
/* @__PURE__ */
|
|
5617
|
+
/* @__PURE__ */ jsx8(
|
|
5222
5618
|
StripeElements,
|
|
5223
5619
|
{
|
|
5224
5620
|
stripe: stripeInstance,
|
|
5225
5621
|
options: apmInlineOptions,
|
|
5226
|
-
children: /* @__PURE__ */
|
|
5622
|
+
children: /* @__PURE__ */ jsx8(
|
|
5227
5623
|
StripeMethodInlineForm,
|
|
5228
5624
|
{
|
|
5229
5625
|
method: expandedApmMethod,
|
|
@@ -5251,14 +5647,14 @@ function SplitCardFormInner({
|
|
|
5251
5647
|
] }) })
|
|
5252
5648
|
] });
|
|
5253
5649
|
}
|
|
5254
|
-
return /* @__PURE__ */
|
|
5255
|
-
/* @__PURE__ */
|
|
5256
|
-
overlayStatus && /* @__PURE__ */
|
|
5257
|
-
/* @__PURE__ */
|
|
5650
|
+
return /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
5651
|
+
/* @__PURE__ */ jsx8(FloPayKeyframes, {}),
|
|
5652
|
+
overlayStatus && /* @__PURE__ */ jsx8(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
5653
|
+
/* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
5258
5654
|
renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
|
|
5259
5655
|
renderStripeGateDebug("flopay-stripe-gate-debug-default"),
|
|
5260
|
-
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */
|
|
5261
|
-
paypalDirectRetry && /* @__PURE__ */
|
|
5656
|
+
shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
5657
|
+
paypalDirectRetry && /* @__PURE__ */ jsx8(
|
|
5262
5658
|
"div",
|
|
5263
5659
|
{
|
|
5264
5660
|
"data-testid": "flopay-paypal-direct-retry-notice-default",
|
|
@@ -5274,7 +5670,7 @@ function SplitCardFormInner({
|
|
|
5274
5670
|
children: "Please confirm your PayPal payment to complete checkout."
|
|
5275
5671
|
}
|
|
5276
5672
|
),
|
|
5277
|
-
/* @__PURE__ */
|
|
5673
|
+
/* @__PURE__ */ jsx8(
|
|
5278
5674
|
DirectPayPalButton,
|
|
5279
5675
|
{
|
|
5280
5676
|
sessionId,
|
|
@@ -5301,7 +5697,7 @@ function SplitCardFormInner({
|
|
|
5301
5697
|
paypalDirectRetry?.orderId ?? "fresh"
|
|
5302
5698
|
)
|
|
5303
5699
|
] }),
|
|
5304
|
-
shouldRenderStripePayPal && /* @__PURE__ */
|
|
5700
|
+
shouldRenderStripePayPal && /* @__PURE__ */ jsx8(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx8(
|
|
5305
5701
|
PayPalButtonInner,
|
|
5306
5702
|
{
|
|
5307
5703
|
sessionId,
|
|
@@ -5319,7 +5715,7 @@ function SplitCardFormInner({
|
|
|
5319
5715
|
placeholderBorderRadius: buttonBorderRadius
|
|
5320
5716
|
}
|
|
5321
5717
|
) }),
|
|
5322
|
-
shouldRenderWallets && /* @__PURE__ */
|
|
5718
|
+
shouldRenderWallets && /* @__PURE__ */ jsx8(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx8(
|
|
5323
5719
|
WalletButtonInner,
|
|
5324
5720
|
{
|
|
5325
5721
|
sessionId,
|
|
@@ -5337,7 +5733,7 @@ function SplitCardFormInner({
|
|
|
5337
5733
|
placeholderBorderRadius: buttonBorderRadius
|
|
5338
5734
|
}
|
|
5339
5735
|
) }),
|
|
5340
|
-
shouldRenderPaymentElement && /* @__PURE__ */
|
|
5736
|
+
shouldRenderPaymentElement && /* @__PURE__ */ jsx8(
|
|
5341
5737
|
StripePaymentElementInner,
|
|
5342
5738
|
{
|
|
5343
5739
|
sessionId,
|
|
@@ -5370,7 +5766,7 @@ function SplitCardFormInner({
|
|
|
5370
5766
|
}
|
|
5371
5767
|
)
|
|
5372
5768
|
] }),
|
|
5373
|
-
showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */
|
|
5769
|
+
showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ jsxs5("div", { style: {
|
|
5374
5770
|
display: "flex",
|
|
5375
5771
|
alignItems: "center",
|
|
5376
5772
|
gap: "0.75rem",
|
|
@@ -5378,9 +5774,9 @@ function SplitCardFormInner({
|
|
|
5378
5774
|
color: "#999",
|
|
5379
5775
|
fontSize: "0.85rem"
|
|
5380
5776
|
}, children: [
|
|
5381
|
-
/* @__PURE__ */
|
|
5382
|
-
/* @__PURE__ */
|
|
5383
|
-
/* @__PURE__ */
|
|
5777
|
+
/* @__PURE__ */ jsx8("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
|
|
5778
|
+
/* @__PURE__ */ jsx8("span", { children: "or pay with card" }),
|
|
5779
|
+
/* @__PURE__ */ jsx8("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
|
|
5384
5780
|
] }),
|
|
5385
5781
|
showStripe && cardFormBlock
|
|
5386
5782
|
] });
|
|
@@ -5410,6 +5806,9 @@ async function confirmResumeIntent(stripe, clientSecret, data, isSetupIntent) {
|
|
|
5410
5806
|
const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, data);
|
|
5411
5807
|
return { error, intent: paymentIntent ?? null };
|
|
5412
5808
|
}
|
|
5809
|
+
function withCheckoutMethod(error, checkoutMethod) {
|
|
5810
|
+
return Object.assign(error, { checkoutMethod });
|
|
5811
|
+
}
|
|
5413
5812
|
function getRedirectResultFromCheckoutProcessError(error) {
|
|
5414
5813
|
if (!error?.type || !error.threeDSecureToken) {
|
|
5415
5814
|
return null;
|
|
@@ -5631,7 +6030,7 @@ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment fai
|
|
|
5631
6030
|
const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
|
|
5632
6031
|
const rawMessage = error?.message ?? fallbackMessage;
|
|
5633
6032
|
const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
|
|
5634
|
-
return
|
|
6033
|
+
return withCheckoutMethod(
|
|
5635
6034
|
new FloPayError4(
|
|
5636
6035
|
message,
|
|
5637
6036
|
"api_error",
|
|
@@ -5639,7 +6038,7 @@ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment fai
|
|
|
5639
6038
|
code: error?.gatewayErrorCode
|
|
5640
6039
|
}
|
|
5641
6040
|
),
|
|
5642
|
-
|
|
6041
|
+
checkoutMethod
|
|
5643
6042
|
);
|
|
5644
6043
|
}
|
|
5645
6044
|
function resolveSavedPaymentReturnUrl(session) {
|
|
@@ -5725,7 +6124,7 @@ async function recover3DSRedirectResult({
|
|
|
5725
6124
|
return null;
|
|
5726
6125
|
}
|
|
5727
6126
|
try {
|
|
5728
|
-
const api = new PaymentAPI3(billingApiUrl);
|
|
6127
|
+
const api = new PaymentAPI3(billingApiUrl, { telemetry: false });
|
|
5729
6128
|
const unified = await api.getUnifiedCheckoutSession(sessionId, nonce);
|
|
5730
6129
|
const refreshedToken = unified.data.stripe?.clientSecret;
|
|
5731
6130
|
if (isStripePaymentIntentClientSecret(refreshedToken)) {
|
|
@@ -5744,7 +6143,8 @@ async function processSavedPaymentForMode({
|
|
|
5744
6143
|
session,
|
|
5745
6144
|
nonce,
|
|
5746
6145
|
tokenizedData,
|
|
5747
|
-
returnUrl
|
|
6146
|
+
returnUrl,
|
|
6147
|
+
telemetry
|
|
5748
6148
|
}) {
|
|
5749
6149
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
5750
6150
|
const resolvedSessionId = sessionId ?? session.id;
|
|
@@ -5755,7 +6155,10 @@ async function processSavedPaymentForMode({
|
|
|
5755
6155
|
const lastName = session.customer?.lastName ?? session.accountData?.lastName ?? "";
|
|
5756
6156
|
const country = session.customer?.country ?? session.accountData?.country ?? void 0;
|
|
5757
6157
|
const zip = session.customer?.zip ?? session.accountData?.zip ?? void 0;
|
|
5758
|
-
const api = new PaymentAPI3(
|
|
6158
|
+
const api = new PaymentAPI3(
|
|
6159
|
+
baseUrl,
|
|
6160
|
+
telemetry === false ? { telemetry: false } : void 0
|
|
6161
|
+
);
|
|
5759
6162
|
const response = await retryOnceOnFetchFailure(() => api.processPayment(customerId, {
|
|
5760
6163
|
sessionId: resolvedSessionId,
|
|
5761
6164
|
nonce: resolvedNonce,
|
|
@@ -5807,13 +6210,13 @@ async function processSavedPaymentForMode({
|
|
|
5807
6210
|
if (recoveredRedirect) {
|
|
5808
6211
|
return recoveredRedirect;
|
|
5809
6212
|
}
|
|
5810
|
-
throw
|
|
6213
|
+
throw withCheckoutMethod(
|
|
5811
6214
|
new FloPayError4(
|
|
5812
6215
|
"Your card requires authentication. Please enter your payment details below.",
|
|
5813
6216
|
"api_error",
|
|
5814
6217
|
{ code: "authentication_required" }
|
|
5815
6218
|
),
|
|
5816
|
-
|
|
6219
|
+
"card"
|
|
5817
6220
|
);
|
|
5818
6221
|
}
|
|
5819
6222
|
throw new FloPayError4(
|
|
@@ -5832,7 +6235,8 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5832
6235
|
billingApiUrl,
|
|
5833
6236
|
sessionId,
|
|
5834
6237
|
session,
|
|
5835
|
-
returnUrl
|
|
6238
|
+
returnUrl,
|
|
6239
|
+
telemetry
|
|
5836
6240
|
}) {
|
|
5837
6241
|
const stripe = flopay?.getRawProvider();
|
|
5838
6242
|
if (!stripe) {
|
|
@@ -5840,13 +6244,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5840
6244
|
}
|
|
5841
6245
|
if (redirectResult.type === "3ds_required") {
|
|
5842
6246
|
if (!attempt3DS || !redirectResult.threeDSecureToken) {
|
|
5843
|
-
throw
|
|
6247
|
+
throw withCheckoutMethod(
|
|
5844
6248
|
new FloPayError4(
|
|
5845
6249
|
"Your card requires authentication. Please enter your payment details below.",
|
|
5846
6250
|
"api_error",
|
|
5847
6251
|
{ code: "authentication_required" }
|
|
5848
6252
|
),
|
|
5849
|
-
|
|
6253
|
+
"card"
|
|
5850
6254
|
);
|
|
5851
6255
|
}
|
|
5852
6256
|
const isSetupIntent = isSetupIntentClientSecret3(redirectResult.threeDSecureToken);
|
|
@@ -5855,13 +6259,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5855
6259
|
const retrieved = await retrieveResumeIntent(stripe, redirectResult.threeDSecureToken, isSetupIntent);
|
|
5856
6260
|
if (retrieved) {
|
|
5857
6261
|
if (retrieved.error) {
|
|
5858
|
-
throw
|
|
6262
|
+
throw withCheckoutMethod(
|
|
5859
6263
|
new FloPayError4(
|
|
5860
6264
|
retrieved.error.message ?? `Failed to retrieve 3DS ${isSetupIntent ? "setup" : "payment"} status.`,
|
|
5861
6265
|
"api_error",
|
|
5862
6266
|
{ code: retrieved.error.code }
|
|
5863
6267
|
),
|
|
5864
|
-
|
|
6268
|
+
"card"
|
|
5865
6269
|
);
|
|
5866
6270
|
}
|
|
5867
6271
|
const existingIntent = retrieved.intent;
|
|
@@ -5884,13 +6288,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5884
6288
|
) : null;
|
|
5885
6289
|
if (confirmed) {
|
|
5886
6290
|
if (confirmed.error) {
|
|
5887
|
-
throw
|
|
6291
|
+
throw withCheckoutMethod(
|
|
5888
6292
|
new FloPayError4(
|
|
5889
6293
|
confirmed.error.message ?? "3DS authentication failed.",
|
|
5890
6294
|
"api_error",
|
|
5891
6295
|
{ code: confirmed.error.code }
|
|
5892
6296
|
),
|
|
5893
|
-
|
|
6297
|
+
"card"
|
|
5894
6298
|
);
|
|
5895
6299
|
}
|
|
5896
6300
|
paymentIntent = confirmed.intent;
|
|
@@ -5899,13 +6303,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5899
6303
|
clientSecret: redirectResult.threeDSecureToken
|
|
5900
6304
|
});
|
|
5901
6305
|
if (nextAction.error) {
|
|
5902
|
-
throw
|
|
6306
|
+
throw withCheckoutMethod(
|
|
5903
6307
|
new FloPayError4(
|
|
5904
6308
|
nextAction.error.message ?? "3DS authentication failed.",
|
|
5905
6309
|
"api_error",
|
|
5906
6310
|
{ code: nextAction.error.code }
|
|
5907
6311
|
),
|
|
5908
|
-
|
|
6312
|
+
"card"
|
|
5909
6313
|
);
|
|
5910
6314
|
}
|
|
5911
6315
|
paymentIntent = (isSetupIntent ? nextAction.setupIntent : nextAction.paymentIntent) ?? null;
|
|
@@ -5915,6 +6319,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5915
6319
|
billingApiUrl,
|
|
5916
6320
|
sessionId,
|
|
5917
6321
|
session,
|
|
6322
|
+
telemetry,
|
|
5918
6323
|
tokenizedData: {
|
|
5919
6324
|
id: paymentIntent.id,
|
|
5920
6325
|
type: "card",
|
|
@@ -5936,20 +6341,21 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5936
6341
|
billingApiUrl,
|
|
5937
6342
|
sessionId,
|
|
5938
6343
|
session,
|
|
5939
|
-
returnUrl
|
|
6344
|
+
returnUrl,
|
|
6345
|
+
telemetry
|
|
5940
6346
|
});
|
|
5941
6347
|
}
|
|
5942
|
-
throw
|
|
6348
|
+
throw withCheckoutMethod(
|
|
5943
6349
|
new FloPayError4("3DS authentication did not complete successfully.", "api_error"),
|
|
5944
|
-
|
|
6350
|
+
"card"
|
|
5945
6351
|
);
|
|
5946
6352
|
}
|
|
5947
6353
|
if (redirectResult.type === "paypal_redirect_required") {
|
|
5948
6354
|
const paypalStripe = (paypalFlopay ?? flopay)?.getRawProvider();
|
|
5949
6355
|
if (!paypalStripe) {
|
|
5950
|
-
throw
|
|
6356
|
+
throw withCheckoutMethod(
|
|
5951
6357
|
new FloPayError4("PayPal is not available.", "api_error"),
|
|
5952
|
-
|
|
6358
|
+
"paypal"
|
|
5953
6359
|
);
|
|
5954
6360
|
}
|
|
5955
6361
|
if (redirectResult.paymentMethodId) {
|
|
@@ -5957,13 +6363,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5957
6363
|
clientSecret: redirectResult.threeDSecureToken
|
|
5958
6364
|
});
|
|
5959
6365
|
if (error2) {
|
|
5960
|
-
throw
|
|
6366
|
+
throw withCheckoutMethod(
|
|
5961
6367
|
new FloPayError4(
|
|
5962
6368
|
error2.message ?? "PayPal authorization failed.",
|
|
5963
6369
|
"api_error",
|
|
5964
6370
|
{ code: error2.code }
|
|
5965
6371
|
),
|
|
5966
|
-
|
|
6372
|
+
"paypal"
|
|
5967
6373
|
);
|
|
5968
6374
|
}
|
|
5969
6375
|
return {
|
|
@@ -5980,13 +6386,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
5980
6386
|
redirect: "if_required"
|
|
5981
6387
|
});
|
|
5982
6388
|
if (error) {
|
|
5983
|
-
throw
|
|
6389
|
+
throw withCheckoutMethod(
|
|
5984
6390
|
new FloPayError4(
|
|
5985
6391
|
error.message ?? "PayPal authorization failed.",
|
|
5986
6392
|
"api_error",
|
|
5987
6393
|
{ code: error.code }
|
|
5988
6394
|
),
|
|
5989
|
-
|
|
6395
|
+
"paypal"
|
|
5990
6396
|
);
|
|
5991
6397
|
}
|
|
5992
6398
|
return {
|
|
@@ -6042,7 +6448,8 @@ async function loadSavedPaymentProviders({
|
|
|
6042
6448
|
publishableKey,
|
|
6043
6449
|
paypalPublishableKey,
|
|
6044
6450
|
billingApiUrl,
|
|
6045
|
-
locale
|
|
6451
|
+
locale,
|
|
6452
|
+
telemetry
|
|
6046
6453
|
}) {
|
|
6047
6454
|
if (!publishableKey) {
|
|
6048
6455
|
return { flopay: null, paypalFlopay: null };
|
|
@@ -6051,11 +6458,13 @@ async function loadSavedPaymentProviders({
|
|
|
6051
6458
|
const [instance, paypalInstanceOrError] = await Promise.all([
|
|
6052
6459
|
loadFloPay(publishableKey, {
|
|
6053
6460
|
billingApiUrl,
|
|
6054
|
-
locale
|
|
6461
|
+
locale,
|
|
6462
|
+
telemetry
|
|
6055
6463
|
}),
|
|
6056
6464
|
needsSeparatePaypal ? loadFloPay(paypalPublishableKey, {
|
|
6057
6465
|
billingApiUrl,
|
|
6058
|
-
locale
|
|
6466
|
+
locale,
|
|
6467
|
+
telemetry
|
|
6059
6468
|
}).catch((err) => {
|
|
6060
6469
|
console.warn("[FloPay] Failed to load PayPal Stripe instance:", err);
|
|
6061
6470
|
return null;
|
|
@@ -6068,13 +6477,40 @@ async function loadSavedPaymentProviders({
|
|
|
6068
6477
|
}
|
|
6069
6478
|
|
|
6070
6479
|
// src/flopay-checkout.tsx
|
|
6071
|
-
import { Fragment as Fragment3, jsx as
|
|
6480
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
6072
6481
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
|
|
6073
6482
|
var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
|
|
6074
6483
|
var sessionInflightMap = /* @__PURE__ */ new Map();
|
|
6075
6484
|
function sleep(ms) {
|
|
6076
6485
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6077
6486
|
}
|
|
6487
|
+
function createStandaloneTelemetryReporter(billingApiUrl, enabled, context) {
|
|
6488
|
+
const reporter = createTelemetryBridge({
|
|
6489
|
+
billingApiUrl,
|
|
6490
|
+
sdkPackage: "@flopay/react",
|
|
6491
|
+
sdkVersion: SDK_VERSION2,
|
|
6492
|
+
enabled: enabled !== false
|
|
6493
|
+
});
|
|
6494
|
+
reporter.beginCheckout(context);
|
|
6495
|
+
return reporter;
|
|
6496
|
+
}
|
|
6497
|
+
function finishStandaloneTelemetry(reporter) {
|
|
6498
|
+
void reporter.flush().catch(() => {
|
|
6499
|
+
}).finally(() => reporter.destroy());
|
|
6500
|
+
}
|
|
6501
|
+
function reportStandaloneTelemetryError(billingApiUrl, enabled, context, errorCode, stage) {
|
|
6502
|
+
const reporter = createStandaloneTelemetryReporter(billingApiUrl, enabled, context);
|
|
6503
|
+
reporter.error({
|
|
6504
|
+
errorCode,
|
|
6505
|
+
stage,
|
|
6506
|
+
paymentMethodCategory: "unknown",
|
|
6507
|
+
...stage === "session_read" ? { requestCategory: "session_read" } : {}
|
|
6508
|
+
});
|
|
6509
|
+
finishStandaloneTelemetry(reporter);
|
|
6510
|
+
}
|
|
6511
|
+
function isExpectedExistingSessionError(error) {
|
|
6512
|
+
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";
|
|
6513
|
+
}
|
|
6078
6514
|
function resolveDirectPaypalConfig(unified) {
|
|
6079
6515
|
const clientId = unified?.data.paypal?.publishableKey;
|
|
6080
6516
|
if (!clientId) return void 0;
|
|
@@ -6179,6 +6615,7 @@ function FloPayCheckout({
|
|
|
6179
6615
|
nonce: nonceProp,
|
|
6180
6616
|
createSession: createSessionParams,
|
|
6181
6617
|
billingApiUrl,
|
|
6618
|
+
telemetry,
|
|
6182
6619
|
appearance: appearanceOverride,
|
|
6183
6620
|
locale,
|
|
6184
6621
|
loading: loadingNode,
|
|
@@ -6224,9 +6661,9 @@ function FloPayCheckout({
|
|
|
6224
6661
|
const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
|
|
6225
6662
|
const [unified, setUnified] = useState4(null);
|
|
6226
6663
|
const [flopay, setFloPay] = useState4(null);
|
|
6227
|
-
const flopayRef =
|
|
6664
|
+
const flopayRef = useRef6(null);
|
|
6228
6665
|
const [paypalFlopay, setPaypalFloPay] = useState4(null);
|
|
6229
|
-
const paypalFlopayRef =
|
|
6666
|
+
const paypalFlopayRef = useRef6(null);
|
|
6230
6667
|
const [session, setSession] = useState4(null);
|
|
6231
6668
|
const [resolvedSessionId, setResolvedSessionId] = useState4(sessionIdProp ?? "");
|
|
6232
6669
|
const activeSessionId = sessionIdProp ?? resolvedSessionId;
|
|
@@ -6241,20 +6678,30 @@ function FloPayCheckout({
|
|
|
6241
6678
|
const [createSessionPatch, setCreateSessionPatch] = useState4(void 0);
|
|
6242
6679
|
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = useState4("");
|
|
6243
6680
|
const [cardBootstrapPending, setCardBootstrapPending] = useState4(false);
|
|
6244
|
-
const autoCheckoutAttempted =
|
|
6245
|
-
const paypalResumeAttempted =
|
|
6246
|
-
const savedPaymentKeysRef =
|
|
6247
|
-
const
|
|
6681
|
+
const autoCheckoutAttempted = useRef6(false);
|
|
6682
|
+
const paypalResumeAttempted = useRef6(false);
|
|
6683
|
+
const savedPaymentKeysRef = useRef6(null);
|
|
6684
|
+
const telemetryCheckoutContext = useMemo4(() => ({
|
|
6685
|
+
checkoutMode: checkoutModeProp ?? currentMode,
|
|
6686
|
+
layout: children ? "unknown" : layout === "buttons" ? "buttons" : "embedded"
|
|
6687
|
+
}), [checkoutModeProp, children, currentMode, layout]);
|
|
6688
|
+
const onCompleteRef = useRef6(onComplete);
|
|
6248
6689
|
onCompleteRef.current = onComplete;
|
|
6249
|
-
const onErrorRef =
|
|
6690
|
+
const onErrorRef = useRef6(onError);
|
|
6250
6691
|
onErrorRef.current = onError;
|
|
6251
|
-
const onDeclineRef =
|
|
6692
|
+
const onDeclineRef = useRef6(onDecline);
|
|
6252
6693
|
onDeclineRef.current = onDecline;
|
|
6253
|
-
|
|
6694
|
+
useEffect6(() => {
|
|
6695
|
+
getFloPayTelemetryBridge(flopay)?.setCheckoutContext(telemetryCheckoutContext);
|
|
6696
|
+
if (paypalFlopay && paypalFlopay !== flopay) {
|
|
6697
|
+
getFloPayTelemetryBridge(paypalFlopay)?.setCheckoutContext(telemetryCheckoutContext);
|
|
6698
|
+
}
|
|
6699
|
+
}, [flopay, paypalFlopay, telemetryCheckoutContext]);
|
|
6700
|
+
const onSessionCompletedRef = useRef6(onSessionCompleted);
|
|
6254
6701
|
onSessionCompletedRef.current = onSessionCompleted;
|
|
6255
6702
|
useEffect6(() => {
|
|
6256
6703
|
console.info("[FloPay] Checkout initialized", {
|
|
6257
|
-
sdk_version:
|
|
6704
|
+
sdk_version: SDK_VERSION2,
|
|
6258
6705
|
checkout_type: checkoutType,
|
|
6259
6706
|
checkout_layout: checkoutLayout,
|
|
6260
6707
|
billing_api_url: resolvedBillingUrl
|
|
@@ -6287,22 +6734,112 @@ function FloPayCheckout({
|
|
|
6287
6734
|
useEffect6(() => {
|
|
6288
6735
|
setModeError(initialErrorMessage);
|
|
6289
6736
|
}, [initialErrorMessage]);
|
|
6290
|
-
const emitDecline =
|
|
6737
|
+
const emitDecline = useCallback4(
|
|
6291
6738
|
(method, input, overrides) => {
|
|
6292
|
-
|
|
6739
|
+
invokeMerchantCallback(() => {
|
|
6740
|
+
onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
|
|
6741
|
+
});
|
|
6293
6742
|
},
|
|
6294
|
-
[]
|
|
6743
|
+
[invokeMerchantCallback]
|
|
6295
6744
|
);
|
|
6296
|
-
const runSavedPaymentFlow =
|
|
6745
|
+
const runSavedPaymentFlow = useCallback4(
|
|
6297
6746
|
async (sess, options) => {
|
|
6298
6747
|
setModeError(null);
|
|
6299
6748
|
setModeOverlayError(null);
|
|
6300
6749
|
setModeOverlayStatus("processing");
|
|
6301
6750
|
const activeSessionId2 = options?.sessionId ?? sess.id;
|
|
6751
|
+
const activeFloPay = flopayRef.current ?? paypalFlopayRef.current;
|
|
6752
|
+
const activeTelemetry = getFloPayTelemetryBridge(activeFloPay);
|
|
6753
|
+
const standaloneTelemetry = activeFloPay ? null : createStandaloneTelemetryReporter(
|
|
6754
|
+
resolvedBillingUrl,
|
|
6755
|
+
telemetry,
|
|
6756
|
+
telemetryCheckoutContext
|
|
6757
|
+
);
|
|
6758
|
+
const telemetrySource = {
|
|
6759
|
+
log: (input) => {
|
|
6760
|
+
if (activeTelemetry) activeTelemetry.log(input);
|
|
6761
|
+
else standaloneTelemetry?.log(input);
|
|
6762
|
+
},
|
|
6763
|
+
error: (input) => {
|
|
6764
|
+
if (activeTelemetry) activeTelemetry.error(input);
|
|
6765
|
+
else standaloneTelemetry?.error(input);
|
|
6766
|
+
},
|
|
6767
|
+
terminal: (input) => {
|
|
6768
|
+
if (activeTelemetry) activeTelemetry.terminal(input);
|
|
6769
|
+
else standaloneTelemetry?.terminal(input);
|
|
6770
|
+
},
|
|
6771
|
+
performance: (input) => {
|
|
6772
|
+
if (activeTelemetry) activeTelemetry.performance(input);
|
|
6773
|
+
else standaloneTelemetry?.performance(input);
|
|
6774
|
+
},
|
|
6775
|
+
now: () => activeTelemetry?.now() ?? standaloneTelemetry?.now() ?? 0,
|
|
6776
|
+
elapsed: (startedAt) => activeTelemetry?.elapsed(startedAt) ?? Math.max(0, (standaloneTelemetry?.now() ?? startedAt) - startedAt)
|
|
6777
|
+
};
|
|
6778
|
+
const processingStartedAt = telemetrySource.now();
|
|
6779
|
+
let recoveryFlow = Boolean(
|
|
6780
|
+
options?.initialAutoProcessingError || options?.initialAutoProcessingPending
|
|
6781
|
+
);
|
|
6782
|
+
let recoveryStarted = false;
|
|
6783
|
+
let recoveryStartedAt;
|
|
6784
|
+
const startRecovery = () => {
|
|
6785
|
+
if (recoveryStarted) return;
|
|
6786
|
+
recoveryStarted = true;
|
|
6787
|
+
recoveryFlow = true;
|
|
6788
|
+
recoveryStartedAt = telemetrySource.now();
|
|
6789
|
+
telemetrySource.log({
|
|
6790
|
+
name: "checkout.recovery.started",
|
|
6791
|
+
stage: "recovery",
|
|
6792
|
+
paymentMethodCategory: "saved"
|
|
6793
|
+
});
|
|
6794
|
+
telemetrySource.log({
|
|
6795
|
+
name: "operation.recovery.started",
|
|
6796
|
+
stage: "recovery",
|
|
6797
|
+
paymentMethodCategory: "saved"
|
|
6798
|
+
});
|
|
6799
|
+
};
|
|
6800
|
+
let processingFinished = false;
|
|
6801
|
+
const finishProcessing = () => {
|
|
6802
|
+
if (processingFinished) return;
|
|
6803
|
+
processingFinished = true;
|
|
6804
|
+
telemetrySource.log({
|
|
6805
|
+
name: "payment.processing.completed",
|
|
6806
|
+
stage: "processing",
|
|
6807
|
+
paymentMethodCategory: "saved"
|
|
6808
|
+
});
|
|
6809
|
+
telemetrySource.performance({
|
|
6810
|
+
stage: "processing",
|
|
6811
|
+
durationMs: telemetrySource.elapsed(processingStartedAt),
|
|
6812
|
+
durationMode: "machine",
|
|
6813
|
+
paymentMethodCategory: "saved"
|
|
6814
|
+
});
|
|
6815
|
+
if (recoveryStartedAt !== void 0) {
|
|
6816
|
+
telemetrySource.performance({
|
|
6817
|
+
stage: "recovery",
|
|
6818
|
+
durationMs: telemetrySource.elapsed(recoveryStartedAt),
|
|
6819
|
+
durationMode: "machine",
|
|
6820
|
+
paymentMethodCategory: "saved"
|
|
6821
|
+
});
|
|
6822
|
+
}
|
|
6823
|
+
};
|
|
6824
|
+
telemetrySource.log({
|
|
6825
|
+
name: "payment.method.selected",
|
|
6826
|
+
stage: "processing",
|
|
6827
|
+
paymentMethodCategory: "saved"
|
|
6828
|
+
});
|
|
6829
|
+
telemetrySource.log({
|
|
6830
|
+
name: "payment.processing.started",
|
|
6831
|
+
stage: "processing",
|
|
6832
|
+
paymentMethodCategory: "saved"
|
|
6833
|
+
});
|
|
6834
|
+
if (recoveryFlow) {
|
|
6835
|
+
startRecovery();
|
|
6836
|
+
}
|
|
6837
|
+
let completionCallback;
|
|
6302
6838
|
try {
|
|
6303
6839
|
const redirectResult = getRedirectResultFromCheckoutProcessError(options?.initialAutoProcessingError);
|
|
6304
6840
|
let paymentResult;
|
|
6305
6841
|
if (redirectResult) {
|
|
6842
|
+
startRecovery();
|
|
6306
6843
|
if (redirectResult.type === "paypal_redirect_required" && savedPaymentKeysRef.current?.publishableKey) {
|
|
6307
6844
|
persistPayPalResumeState({
|
|
6308
6845
|
sessionId: activeSessionId2,
|
|
@@ -6316,13 +6853,14 @@ function FloPayCheckout({
|
|
|
6316
6853
|
attempt3DS: options?.attempt3DS,
|
|
6317
6854
|
billingApiUrl: resolvedBillingUrl,
|
|
6318
6855
|
sessionId: activeSessionId2,
|
|
6319
|
-
session: sess
|
|
6856
|
+
session: sess,
|
|
6857
|
+
telemetry: false
|
|
6320
6858
|
});
|
|
6321
6859
|
if (redirectResult.type === "paypal_redirect_required") {
|
|
6322
6860
|
clearPayPalResumeState();
|
|
6323
6861
|
}
|
|
6324
6862
|
} else if (options?.initialAutoProcessingPending) {
|
|
6325
|
-
const api = new PaymentAPI4(resolvedBillingUrl);
|
|
6863
|
+
const api = new PaymentAPI4(resolvedBillingUrl, { telemetry: false });
|
|
6326
6864
|
const completed = await api.waitForCheckoutSessionCompletion(options.initialAutoProcessingPending.sessionId, {
|
|
6327
6865
|
initialDelayMs: options.initialAutoProcessingPending.retryAfterMs
|
|
6328
6866
|
});
|
|
@@ -6350,11 +6888,13 @@ function FloPayCheckout({
|
|
|
6350
6888
|
const result = await processSavedPaymentForMode({
|
|
6351
6889
|
billingApiUrl: resolvedBillingUrl,
|
|
6352
6890
|
sessionId: activeSessionId2,
|
|
6353
|
-
session: sess
|
|
6891
|
+
session: sess,
|
|
6892
|
+
telemetry: false
|
|
6354
6893
|
});
|
|
6355
6894
|
if (result.type === "success") {
|
|
6356
6895
|
paymentResult = result.result;
|
|
6357
6896
|
} else {
|
|
6897
|
+
startRecovery();
|
|
6358
6898
|
if (result.type === "paypal_redirect_required" && savedPaymentKeysRef.current?.publishableKey) {
|
|
6359
6899
|
persistPayPalResumeState({
|
|
6360
6900
|
sessionId: activeSessionId2,
|
|
@@ -6368,7 +6908,8 @@ function FloPayCheckout({
|
|
|
6368
6908
|
attempt3DS: options?.attempt3DS,
|
|
6369
6909
|
billingApiUrl: resolvedBillingUrl,
|
|
6370
6910
|
sessionId: activeSessionId2,
|
|
6371
|
-
session: sess
|
|
6911
|
+
session: sess,
|
|
6912
|
+
telemetry: false
|
|
6372
6913
|
});
|
|
6373
6914
|
if (result.type === "paypal_redirect_required") {
|
|
6374
6915
|
clearPayPalResumeState();
|
|
@@ -6376,20 +6917,57 @@ function FloPayCheckout({
|
|
|
6376
6917
|
}
|
|
6377
6918
|
}
|
|
6378
6919
|
if (activeSessionId2) markSessionRecentlyCompleted(activeSessionId2);
|
|
6920
|
+
finishProcessing();
|
|
6921
|
+
if (recoveryFlow) {
|
|
6922
|
+
telemetrySource.log({
|
|
6923
|
+
name: "checkout.recovery.completed",
|
|
6924
|
+
stage: "recovery",
|
|
6925
|
+
paymentMethodCategory: "saved"
|
|
6926
|
+
});
|
|
6927
|
+
telemetrySource.log({
|
|
6928
|
+
name: "operation.recovery.completed",
|
|
6929
|
+
stage: "recovery",
|
|
6930
|
+
paymentMethodCategory: "saved"
|
|
6931
|
+
});
|
|
6932
|
+
}
|
|
6933
|
+
telemetrySource.terminal({
|
|
6934
|
+
outcome: "payment_succeeded",
|
|
6935
|
+
paymentMethodCategory: "saved"
|
|
6936
|
+
});
|
|
6379
6937
|
setModeOverlayStatus("success");
|
|
6380
6938
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
6381
|
-
onCompleteRef.current?.(paymentResult);
|
|
6382
|
-
return true;
|
|
6939
|
+
completionCallback = () => onCompleteRef.current?.(paymentResult);
|
|
6383
6940
|
} catch (err) {
|
|
6384
6941
|
const floPayErr = normalizeSavedPaymentError(err);
|
|
6385
6942
|
const method = floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD;
|
|
6386
6943
|
setModeError(floPayErr.message);
|
|
6387
6944
|
setModeOverlayError(floPayErr.message);
|
|
6388
6945
|
if (options?.fallbackToFull) {
|
|
6946
|
+
telemetrySource.log({
|
|
6947
|
+
name: "operation.fallback",
|
|
6948
|
+
stage: "recovery",
|
|
6949
|
+
paymentMethodCategory: "saved"
|
|
6950
|
+
});
|
|
6389
6951
|
setCurrentMode("full");
|
|
6390
6952
|
replaceCheckoutModeQueryParam("full");
|
|
6391
6953
|
}
|
|
6392
|
-
|
|
6954
|
+
finishProcessing();
|
|
6955
|
+
const expectedDecline = Boolean(
|
|
6956
|
+
floPayErr.declineCode || floPayErr.code?.toLowerCase().includes("declin")
|
|
6957
|
+
);
|
|
6958
|
+
if (expectedDecline) {
|
|
6959
|
+
telemetrySource.terminal({
|
|
6960
|
+
outcome: "payment_declined",
|
|
6961
|
+
paymentMethodCategory: "saved"
|
|
6962
|
+
});
|
|
6963
|
+
} else {
|
|
6964
|
+
telemetrySource.error({
|
|
6965
|
+
errorCode: recoveryFlow ? "RECOVERY_FAILED" : "PAYMENT_PROCESSING_FAILED",
|
|
6966
|
+
stage: recoveryFlow ? "recovery" : "processing",
|
|
6967
|
+
paymentMethodCategory: "saved"
|
|
6968
|
+
});
|
|
6969
|
+
}
|
|
6970
|
+
invokeMerchantCallback(() => onErrorRef.current?.(floPayErr));
|
|
6393
6971
|
emitDecline(method, floPayErr, {
|
|
6394
6972
|
code: floPayErr.code,
|
|
6395
6973
|
declineCode: floPayErr.declineCode
|
|
@@ -6399,16 +6977,35 @@ function FloPayCheckout({
|
|
|
6399
6977
|
sleep(PROCESSING_OVERLAY_ERROR_DELAY_MS),
|
|
6400
6978
|
options?.ensureProvidersReady ? options.ensureProvidersReady() : Promise.resolve()
|
|
6401
6979
|
]);
|
|
6980
|
+
if (recoveryFlow) {
|
|
6981
|
+
telemetrySource.log({
|
|
6982
|
+
name: "checkout.recovery.completed",
|
|
6983
|
+
stage: "recovery",
|
|
6984
|
+
paymentMethodCategory: "saved"
|
|
6985
|
+
});
|
|
6986
|
+
telemetrySource.log({
|
|
6987
|
+
name: "operation.recovery.completed",
|
|
6988
|
+
stage: "recovery",
|
|
6989
|
+
paymentMethodCategory: "saved"
|
|
6990
|
+
});
|
|
6991
|
+
}
|
|
6402
6992
|
return false;
|
|
6403
6993
|
} finally {
|
|
6994
|
+
finishProcessing();
|
|
6995
|
+
if (standaloneTelemetry) finishStandaloneTelemetry(standaloneTelemetry);
|
|
6404
6996
|
setModeOverlayStatus(null);
|
|
6405
6997
|
setModeOverlayError(null);
|
|
6406
6998
|
}
|
|
6999
|
+
invokeMerchantCallback(completionCallback);
|
|
7000
|
+
return true;
|
|
6407
7001
|
},
|
|
6408
7002
|
[
|
|
6409
7003
|
emitDecline,
|
|
7004
|
+
invokeMerchantCallback,
|
|
6410
7005
|
normalizeSavedPaymentError,
|
|
6411
|
-
resolvedBillingUrl
|
|
7006
|
+
resolvedBillingUrl,
|
|
7007
|
+
telemetry,
|
|
7008
|
+
telemetryCheckoutContext
|
|
6412
7009
|
]
|
|
6413
7010
|
);
|
|
6414
7011
|
useEffect6(() => {
|
|
@@ -6426,6 +7023,8 @@ function FloPayCheckout({
|
|
|
6426
7023
|
}
|
|
6427
7024
|
paypalResumeAttempted.current = true;
|
|
6428
7025
|
void (async () => {
|
|
7026
|
+
let resumeTelemetry;
|
|
7027
|
+
let redirectResumeStartedAt = 0;
|
|
6429
7028
|
setModeError(null);
|
|
6430
7029
|
setModeOverlayError(null);
|
|
6431
7030
|
setModeOverlayStatus("processing");
|
|
@@ -6433,7 +7032,11 @@ function FloPayCheckout({
|
|
|
6433
7032
|
try {
|
|
6434
7033
|
if (params.get("redirect_status") === "failed") {
|
|
6435
7034
|
throw Object.assign(
|
|
6436
|
-
new FloPayError5(
|
|
7035
|
+
new FloPayError5(
|
|
7036
|
+
"PayPal payment was declined. Please try again.",
|
|
7037
|
+
"api_error",
|
|
7038
|
+
{ declineCode: "paypal_redirect_failed" }
|
|
7039
|
+
),
|
|
6437
7040
|
{ checkoutMethod: "paypal" }
|
|
6438
7041
|
);
|
|
6439
7042
|
}
|
|
@@ -6444,7 +7047,22 @@ function FloPayCheckout({
|
|
|
6444
7047
|
publishableKey: resumeState.publishableKey,
|
|
6445
7048
|
paypalPublishableKey: resumeState.paypalPublishableKey,
|
|
6446
7049
|
billingApiUrl: resolvedBillingUrl,
|
|
6447
|
-
locale
|
|
7050
|
+
locale,
|
|
7051
|
+
telemetry
|
|
7052
|
+
});
|
|
7053
|
+
resumeTelemetry = getFloPayTelemetryBridge(resumePaypalFlopay ?? resumeFlopay);
|
|
7054
|
+
redirectResumeStartedAt = resumeTelemetry?.now() ?? 0;
|
|
7055
|
+
resumeTelemetry?.log({
|
|
7056
|
+
name: "provider.redirect.resumed",
|
|
7057
|
+
stage: "redirect_resume",
|
|
7058
|
+
provider: "paypal",
|
|
7059
|
+
paymentMethodCategory: "paypal"
|
|
7060
|
+
});
|
|
7061
|
+
resumeTelemetry?.log({
|
|
7062
|
+
name: "operation.recovery.started",
|
|
7063
|
+
stage: "recovery",
|
|
7064
|
+
provider: "paypal",
|
|
7065
|
+
paymentMethodCategory: "paypal"
|
|
6448
7066
|
});
|
|
6449
7067
|
const paypalStripe = (resumePaypalFlopay ?? resumeFlopay)?.getRawProvider();
|
|
6450
7068
|
if (!paypalStripe) {
|
|
@@ -6474,7 +7092,7 @@ function FloPayCheckout({
|
|
|
6474
7092
|
const paymentMethodId = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
|
|
6475
7093
|
let finalResultStatus = resultStatus;
|
|
6476
7094
|
if (resumeState.sessionId) {
|
|
6477
|
-
const resumeApi = new PaymentAPI4(resolvedBillingUrl);
|
|
7095
|
+
const resumeApi = new PaymentAPI4(resolvedBillingUrl, { telemetry: false });
|
|
6478
7096
|
const resumeSessionResult = await resumeApi.getUnifiedCheckoutSession(resumeState.sessionId);
|
|
6479
7097
|
const resumeSession = resumeSessionResult.data.session;
|
|
6480
7098
|
if (resumeSession && resumeSession.status !== "complete") {
|
|
@@ -6482,6 +7100,7 @@ function FloPayCheckout({
|
|
|
6482
7100
|
billingApiUrl: resolvedBillingUrl,
|
|
6483
7101
|
sessionId: resumeState.sessionId,
|
|
6484
7102
|
session: resumeSession,
|
|
7103
|
+
telemetry: false,
|
|
6485
7104
|
tokenizedData: {
|
|
6486
7105
|
id: paymentMethodId ?? paymentIntent.id,
|
|
6487
7106
|
type: "card",
|
|
@@ -6499,20 +7118,84 @@ function FloPayCheckout({
|
|
|
6499
7118
|
}
|
|
6500
7119
|
}
|
|
6501
7120
|
if (resumeState.sessionId) markSessionRecentlyCompleted(resumeState.sessionId);
|
|
7121
|
+
resumeTelemetry?.log({
|
|
7122
|
+
name: "operation.recovery.completed",
|
|
7123
|
+
stage: "recovery",
|
|
7124
|
+
provider: "paypal",
|
|
7125
|
+
paymentMethodCategory: "paypal"
|
|
7126
|
+
});
|
|
7127
|
+
resumeTelemetry?.performance({
|
|
7128
|
+
stage: "redirect_resume",
|
|
7129
|
+
durationMs: resumeTelemetry.elapsed(redirectResumeStartedAt),
|
|
7130
|
+
durationMode: "machine",
|
|
7131
|
+
provider: "paypal",
|
|
7132
|
+
paymentMethodCategory: "paypal"
|
|
7133
|
+
});
|
|
7134
|
+
resumeTelemetry?.terminal({
|
|
7135
|
+
outcome: "payment_succeeded",
|
|
7136
|
+
provider: "paypal",
|
|
7137
|
+
paymentMethodCategory: "paypal"
|
|
7138
|
+
});
|
|
6502
7139
|
setModeOverlayStatus("success");
|
|
6503
7140
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
6504
|
-
onCompleteRef.current?.({
|
|
7141
|
+
invokeMerchantCallback(() => onCompleteRef.current?.({
|
|
6505
7142
|
status: finalResultStatus,
|
|
6506
7143
|
paymentIntentId: paymentIntent.id,
|
|
6507
7144
|
paymentMethodId,
|
|
6508
7145
|
checkoutMethod: "paypal"
|
|
6509
|
-
});
|
|
7146
|
+
}));
|
|
6510
7147
|
} catch (err) {
|
|
6511
7148
|
const floPayErr = normalizeSavedPaymentError(err);
|
|
6512
7149
|
const method = floPayErr.checkoutMethod ?? "paypal";
|
|
7150
|
+
const expectedDecline = Boolean(
|
|
7151
|
+
floPayErr.declineCode || floPayErr.code?.toLowerCase().includes("declin")
|
|
7152
|
+
);
|
|
7153
|
+
if (resumeTelemetry) {
|
|
7154
|
+
resumeTelemetry.performance({
|
|
7155
|
+
stage: "redirect_resume",
|
|
7156
|
+
durationMs: resumeTelemetry.elapsed(redirectResumeStartedAt),
|
|
7157
|
+
durationMode: "machine",
|
|
7158
|
+
provider: "paypal",
|
|
7159
|
+
paymentMethodCategory: "paypal"
|
|
7160
|
+
});
|
|
7161
|
+
if (expectedDecline) {
|
|
7162
|
+
resumeTelemetry.terminal({
|
|
7163
|
+
outcome: "payment_declined",
|
|
7164
|
+
provider: "paypal",
|
|
7165
|
+
paymentMethodCategory: "paypal"
|
|
7166
|
+
});
|
|
7167
|
+
} else {
|
|
7168
|
+
resumeTelemetry.error({
|
|
7169
|
+
errorCode: "REDIRECT_RESUME_FAILED",
|
|
7170
|
+
stage: "redirect_resume",
|
|
7171
|
+
provider: "paypal",
|
|
7172
|
+
paymentMethodCategory: "paypal"
|
|
7173
|
+
});
|
|
7174
|
+
}
|
|
7175
|
+
} else if (expectedDecline) {
|
|
7176
|
+
const reporter = createStandaloneTelemetryReporter(
|
|
7177
|
+
resolvedBillingUrl,
|
|
7178
|
+
telemetry,
|
|
7179
|
+
telemetryCheckoutContext
|
|
7180
|
+
);
|
|
7181
|
+
reporter.terminal({
|
|
7182
|
+
outcome: "payment_declined",
|
|
7183
|
+
provider: "paypal",
|
|
7184
|
+
paymentMethodCategory: "paypal"
|
|
7185
|
+
});
|
|
7186
|
+
finishStandaloneTelemetry(reporter);
|
|
7187
|
+
} else {
|
|
7188
|
+
reportStandaloneTelemetryError(
|
|
7189
|
+
resolvedBillingUrl,
|
|
7190
|
+
telemetry,
|
|
7191
|
+
telemetryCheckoutContext,
|
|
7192
|
+
"REDIRECT_RESUME_FAILED",
|
|
7193
|
+
"redirect_resume"
|
|
7194
|
+
);
|
|
7195
|
+
}
|
|
6513
7196
|
setModeError(floPayErr.message);
|
|
6514
7197
|
setModeOverlayError(floPayErr.message);
|
|
6515
|
-
onErrorRef.current?.(floPayErr);
|
|
7198
|
+
invokeMerchantCallback(() => onErrorRef.current?.(floPayErr));
|
|
6516
7199
|
emitDecline(method, floPayErr, {
|
|
6517
7200
|
code: floPayErr.code,
|
|
6518
7201
|
declineCode: floPayErr.declineCode
|
|
@@ -6527,8 +7210,8 @@ function FloPayCheckout({
|
|
|
6527
7210
|
setConfirmProcessing(false);
|
|
6528
7211
|
}
|
|
6529
7212
|
})();
|
|
6530
|
-
}, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
|
|
6531
|
-
const initializedHashRef =
|
|
7213
|
+
}, [emitDecline, invokeMerchantCallback, locale, normalizeSavedPaymentError, resolvedBillingUrl, telemetry]);
|
|
7214
|
+
const initializedHashRef = useRef6(null);
|
|
6532
7215
|
function hashCreateParams(params) {
|
|
6533
7216
|
const key = JSON.stringify({
|
|
6534
7217
|
c: params?.clientId,
|
|
@@ -6565,7 +7248,7 @@ function FloPayCheckout({
|
|
|
6565
7248
|
() => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
|
|
6566
7249
|
[effectiveCreateSession]
|
|
6567
7250
|
);
|
|
6568
|
-
const createSessionParamsRef =
|
|
7251
|
+
const createSessionParamsRef = useRef6(effectiveCreateSession);
|
|
6569
7252
|
createSessionParamsRef.current = effectiveCreateSession;
|
|
6570
7253
|
useEffect6(() => {
|
|
6571
7254
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
@@ -6577,44 +7260,107 @@ function FloPayCheckout({
|
|
|
6577
7260
|
setModeOverlayStatus(null);
|
|
6578
7261
|
}, [createSessionHash, initialErrorMessage, sessionIdProp]);
|
|
6579
7262
|
async function resolveInlineSession(params, cacheKey) {
|
|
6580
|
-
const
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
7263
|
+
const reporter = createStandaloneTelemetryReporter(
|
|
7264
|
+
resolvedBillingUrl,
|
|
7265
|
+
telemetry,
|
|
7266
|
+
telemetryCheckoutContext
|
|
7267
|
+
);
|
|
7268
|
+
const api = new PaymentAPI4(resolvedBillingUrl, { telemetry: false });
|
|
7269
|
+
try {
|
|
7270
|
+
const cached = readCachedInlineSession(cacheKey);
|
|
7271
|
+
reporter.log({
|
|
7272
|
+
name: cached ? "operation.cache.hit" : "operation.cache.miss",
|
|
7273
|
+
stage: "session_create",
|
|
7274
|
+
requestCategory: "session_create"
|
|
7275
|
+
});
|
|
7276
|
+
let sid = cached?.sid ?? null;
|
|
7277
|
+
let realResult = null;
|
|
7278
|
+
if (sid) {
|
|
7279
|
+
try {
|
|
7280
|
+
realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
|
|
7281
|
+
const status = realResult.data.session?.status;
|
|
7282
|
+
if (status === "complete") {
|
|
7283
|
+
if (wasSessionRecentlyCompleted(sid)) {
|
|
7284
|
+
return { sid, result: realResult };
|
|
7285
|
+
}
|
|
7286
|
+
clearCachedInlineSession(cacheKey);
|
|
7287
|
+
sid = null;
|
|
7288
|
+
realResult = null;
|
|
6591
7289
|
}
|
|
7290
|
+
} catch {
|
|
7291
|
+
reporter.log({
|
|
7292
|
+
name: "operation.fallback",
|
|
7293
|
+
stage: "session_read",
|
|
7294
|
+
requestCategory: "session_read"
|
|
7295
|
+
});
|
|
6592
7296
|
clearCachedInlineSession(cacheKey);
|
|
6593
7297
|
sid = null;
|
|
6594
|
-
realResult = null;
|
|
6595
7298
|
}
|
|
6596
|
-
} catch {
|
|
6597
|
-
clearCachedInlineSession(cacheKey);
|
|
6598
|
-
sid = null;
|
|
6599
7299
|
}
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
7300
|
+
if (!sid) {
|
|
7301
|
+
const sessionCreateStartedAt = reporter.now();
|
|
7302
|
+
reporter.log({
|
|
7303
|
+
name: "session.create.started",
|
|
7304
|
+
stage: "session_create",
|
|
7305
|
+
requestCategory: "session_create"
|
|
7306
|
+
});
|
|
7307
|
+
const paramsWithAnalytics = {
|
|
7308
|
+
...params,
|
|
7309
|
+
avsCheck: !!enableAVS,
|
|
7310
|
+
avsConfig: typeof enableAVS === "object" ? enableAVS : void 0,
|
|
7311
|
+
checkoutType: "embedded_checkout",
|
|
7312
|
+
checkoutLayout: children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout"
|
|
7313
|
+
};
|
|
7314
|
+
try {
|
|
7315
|
+
realResult = await api.createAndFetchSession(paramsWithAnalytics);
|
|
7316
|
+
reporter.log({
|
|
7317
|
+
name: "session.request.completed",
|
|
7318
|
+
stage: "session_complete",
|
|
7319
|
+
requestCategory: "session_create",
|
|
7320
|
+
statusClass: "2xx"
|
|
7321
|
+
});
|
|
7322
|
+
reporter.performance({
|
|
7323
|
+
stage: "session_create",
|
|
7324
|
+
durationMs: reporter.now() - sessionCreateStartedAt,
|
|
7325
|
+
durationMode: "machine",
|
|
7326
|
+
requestCategory: "session_create",
|
|
7327
|
+
statusClass: "2xx"
|
|
7328
|
+
});
|
|
7329
|
+
} catch (error) {
|
|
7330
|
+
reporter.performance({
|
|
7331
|
+
stage: "session_create",
|
|
7332
|
+
durationMs: reporter.now() - sessionCreateStartedAt,
|
|
7333
|
+
durationMode: "machine",
|
|
7334
|
+
requestCategory: "session_create",
|
|
7335
|
+
statusClass: "network_error"
|
|
7336
|
+
});
|
|
7337
|
+
if (error instanceof FloPayError5 && error.type === "validation_error") {
|
|
7338
|
+
reporter.terminal({
|
|
7339
|
+
outcome: "validation_rejected",
|
|
7340
|
+
stage: "session_create",
|
|
7341
|
+
paymentMethodCategory: "unknown"
|
|
7342
|
+
});
|
|
7343
|
+
} else {
|
|
7344
|
+
reporter.error({
|
|
7345
|
+
errorCode: "CHECKOUT_SESSION_CREATE_FAILED",
|
|
7346
|
+
stage: "session_create",
|
|
7347
|
+
paymentMethodCategory: "unknown",
|
|
7348
|
+
requestCategory: "session_create"
|
|
7349
|
+
});
|
|
7350
|
+
}
|
|
7351
|
+
throw error;
|
|
7352
|
+
}
|
|
7353
|
+
sid = realResult.data.session?.id ?? "";
|
|
7354
|
+
if (sid) {
|
|
7355
|
+
persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
|
|
7356
|
+
}
|
|
6613
7357
|
}
|
|
7358
|
+
return { sid: sid ?? "", result: realResult };
|
|
7359
|
+
} finally {
|
|
7360
|
+
finishStandaloneTelemetry(reporter);
|
|
6614
7361
|
}
|
|
6615
|
-
return { sid: sid ?? "", result: realResult };
|
|
6616
7362
|
}
|
|
6617
|
-
const bootstrapInlineSession =
|
|
7363
|
+
const bootstrapInlineSession = useCallback4(
|
|
6618
7364
|
async (patch) => {
|
|
6619
7365
|
const baseParams = createSessionParamsRef.current;
|
|
6620
7366
|
if (!baseParams) {
|
|
@@ -6658,7 +7404,8 @@ function FloPayCheckout({
|
|
|
6658
7404
|
publishableKey,
|
|
6659
7405
|
paypalPublishableKey,
|
|
6660
7406
|
billingApiUrl: resolvedBillingUrl,
|
|
6661
|
-
locale
|
|
7407
|
+
locale,
|
|
7408
|
+
telemetry
|
|
6662
7409
|
});
|
|
6663
7410
|
flopayRef.current = instance;
|
|
6664
7411
|
setFloPay(instance);
|
|
@@ -6673,9 +7420,9 @@ function FloPayCheckout({
|
|
|
6673
7420
|
}
|
|
6674
7421
|
return resolved;
|
|
6675
7422
|
},
|
|
6676
|
-
[locale, resolvedBillingUrl]
|
|
7423
|
+
[locale, resolvedBillingUrl, telemetry, telemetryCheckoutContext]
|
|
6677
7424
|
);
|
|
6678
|
-
const handleInlineSessionPatch =
|
|
7425
|
+
const handleInlineSessionPatch = useCallback4(async (patch) => {
|
|
6679
7426
|
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
|
|
6680
7427
|
return {
|
|
6681
7428
|
sessionId: resolvedSessionId,
|
|
@@ -6752,7 +7499,9 @@ function FloPayCheckout({
|
|
|
6752
7499
|
setModeOverlayStatus("success");
|
|
6753
7500
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
6754
7501
|
if (!cancelled) {
|
|
6755
|
-
|
|
7502
|
+
invokeMerchantCallback(() => {
|
|
7503
|
+
onCompleteRef.current?.({ status: "succeeded" });
|
|
7504
|
+
});
|
|
6756
7505
|
setModeOverlayStatus(null);
|
|
6757
7506
|
setModeOverlayError(null);
|
|
6758
7507
|
}
|
|
@@ -6772,8 +7521,9 @@ function FloPayCheckout({
|
|
|
6772
7521
|
}
|
|
6773
7522
|
setIsLoading(true);
|
|
6774
7523
|
async function init() {
|
|
7524
|
+
let sessionReadCompleted = false;
|
|
6775
7525
|
try {
|
|
6776
|
-
const api = new PaymentAPI4(resolvedBillingUrl);
|
|
7526
|
+
const api = new PaymentAPI4(resolvedBillingUrl, { telemetry: false });
|
|
6777
7527
|
const result = await api.getUnifiedCheckoutSession(activeSessionId, nonceProp);
|
|
6778
7528
|
if (cancelled) return;
|
|
6779
7529
|
setUnified(result);
|
|
@@ -6784,7 +7534,9 @@ function FloPayCheckout({
|
|
|
6784
7534
|
}
|
|
6785
7535
|
if (sess.status === "complete") {
|
|
6786
7536
|
setIsLoading(false);
|
|
6787
|
-
|
|
7537
|
+
invokeMerchantCallback(() => {
|
|
7538
|
+
onSessionCompletedRef.current?.(sess.successUrl ?? "");
|
|
7539
|
+
});
|
|
6788
7540
|
return;
|
|
6789
7541
|
}
|
|
6790
7542
|
if (sess.status === "expired") {
|
|
@@ -6792,6 +7544,7 @@ function FloPayCheckout({
|
|
|
6792
7544
|
code: "checkout_session_expired"
|
|
6793
7545
|
});
|
|
6794
7546
|
}
|
|
7547
|
+
sessionReadCompleted = true;
|
|
6795
7548
|
const effectiveMode = checkoutModeProp ?? sess.checkoutMode ?? "full";
|
|
6796
7549
|
setCurrentMode(effectiveMode);
|
|
6797
7550
|
const hasPayPalRedirectParams = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("payment_intent");
|
|
@@ -6823,6 +7576,23 @@ function FloPayCheckout({
|
|
|
6823
7576
|
if (!cancelled) setIsLoading(false);
|
|
6824
7577
|
} catch (err) {
|
|
6825
7578
|
if (cancelled) return;
|
|
7579
|
+
if (!(err instanceof FloPayError5)) {
|
|
7580
|
+
reportStandaloneTelemetryError(
|
|
7581
|
+
resolvedBillingUrl,
|
|
7582
|
+
telemetry,
|
|
7583
|
+
telemetryCheckoutContext,
|
|
7584
|
+
"INTERNAL_SDK_ERROR",
|
|
7585
|
+
"checkout_mount"
|
|
7586
|
+
);
|
|
7587
|
+
} else if (!sessionReadCompleted && !isExpectedExistingSessionError(err)) {
|
|
7588
|
+
reportStandaloneTelemetryError(
|
|
7589
|
+
resolvedBillingUrl,
|
|
7590
|
+
telemetry,
|
|
7591
|
+
telemetryCheckoutContext,
|
|
7592
|
+
"NETWORK_REQUEST_FAILED",
|
|
7593
|
+
"session_read"
|
|
7594
|
+
);
|
|
7595
|
+
}
|
|
6826
7596
|
const floPayErr = err instanceof FloPayError5 ? err : new FloPayError5(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
|
|
6827
7597
|
setLoadError(floPayErr);
|
|
6828
7598
|
setIsLoading(false);
|
|
@@ -6844,7 +7614,8 @@ function FloPayCheckout({
|
|
|
6844
7614
|
publishableKey,
|
|
6845
7615
|
paypalPublishableKey,
|
|
6846
7616
|
billingApiUrl: resolvedBillingUrl,
|
|
6847
|
-
locale
|
|
7617
|
+
locale,
|
|
7618
|
+
telemetry
|
|
6848
7619
|
});
|
|
6849
7620
|
flopayRef.current = instance;
|
|
6850
7621
|
setFloPay(instance);
|
|
@@ -6861,10 +7632,11 @@ function FloPayCheckout({
|
|
|
6861
7632
|
createSessionHash,
|
|
6862
7633
|
effectiveCreateSessionMode,
|
|
6863
7634
|
initSessionDependency,
|
|
7635
|
+
invokeMerchantCallback,
|
|
6864
7636
|
nonceProp,
|
|
6865
7637
|
runSavedPaymentFlow
|
|
6866
7638
|
]);
|
|
6867
|
-
const handleConfirmCheckout =
|
|
7639
|
+
const handleConfirmCheckout = useCallback4(async () => {
|
|
6868
7640
|
if (confirmProcessing || !session) return;
|
|
6869
7641
|
setConfirmProcessing(true);
|
|
6870
7642
|
setModeError(null);
|
|
@@ -6920,7 +7692,7 @@ function FloPayCheckout({
|
|
|
6920
7692
|
]
|
|
6921
7693
|
);
|
|
6922
7694
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
|
|
6923
|
-
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */
|
|
7695
|
+
const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ jsx9(
|
|
6924
7696
|
ProcessingOverlay,
|
|
6925
7697
|
{
|
|
6926
7698
|
status: modeOverlayStatus,
|
|
@@ -6929,32 +7701,32 @@ function FloPayCheckout({
|
|
|
6929
7701
|
) : null;
|
|
6930
7702
|
if (isLoading) {
|
|
6931
7703
|
if (loadingNode) {
|
|
6932
|
-
return /* @__PURE__ */
|
|
7704
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
6933
7705
|
loadingNode,
|
|
6934
7706
|
modeOverlay
|
|
6935
7707
|
] });
|
|
6936
7708
|
}
|
|
6937
7709
|
if (layout === "buttons") {
|
|
6938
7710
|
const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
6939
|
-
const skeletonBar = (h) => /* @__PURE__ */
|
|
7711
|
+
const skeletonBar = (h) => /* @__PURE__ */ jsx9("div", { style: {
|
|
6940
7712
|
height: h,
|
|
6941
7713
|
borderRadius: bundleRadius,
|
|
6942
7714
|
background: "#e5e7eb",
|
|
6943
7715
|
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
6944
7716
|
} });
|
|
6945
|
-
return /* @__PURE__ */
|
|
6946
|
-
/* @__PURE__ */
|
|
7717
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7718
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
6947
7719
|
showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6948
7720
|
showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6949
7721
|
showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
6950
|
-
/* @__PURE__ */
|
|
7722
|
+
/* @__PURE__ */ jsx9("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
6951
7723
|
] }),
|
|
6952
7724
|
modeOverlay
|
|
6953
7725
|
] });
|
|
6954
7726
|
}
|
|
6955
|
-
return /* @__PURE__ */
|
|
6956
|
-
/* @__PURE__ */
|
|
6957
|
-
/* @__PURE__ */
|
|
7727
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7728
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
7729
|
+
/* @__PURE__ */ jsx9("div", { style: {
|
|
6958
7730
|
width: 24,
|
|
6959
7731
|
height: 24,
|
|
6960
7732
|
border: "2px solid #e5e7eb",
|
|
@@ -6962,16 +7734,16 @@ function FloPayCheckout({
|
|
|
6962
7734
|
borderRadius: "50%",
|
|
6963
7735
|
animation: "spin 0.6s linear infinite"
|
|
6964
7736
|
} }),
|
|
6965
|
-
/* @__PURE__ */
|
|
7737
|
+
/* @__PURE__ */ jsx9("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
6966
7738
|
] }),
|
|
6967
7739
|
modeOverlay
|
|
6968
7740
|
] });
|
|
6969
7741
|
}
|
|
6970
7742
|
if (loadError) {
|
|
6971
7743
|
if (errorNode) {
|
|
6972
|
-
return /* @__PURE__ */
|
|
7744
|
+
return /* @__PURE__ */ jsx9(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
|
|
6973
7745
|
}
|
|
6974
|
-
return /* @__PURE__ */
|
|
7746
|
+
return /* @__PURE__ */ jsx9(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx9(
|
|
6975
7747
|
"div",
|
|
6976
7748
|
{
|
|
6977
7749
|
role: "alert",
|
|
@@ -6987,8 +7759,8 @@ function FloPayCheckout({
|
|
|
6987
7759
|
) });
|
|
6988
7760
|
}
|
|
6989
7761
|
if (shouldShowInterimButtons) {
|
|
6990
|
-
return /* @__PURE__ */
|
|
6991
|
-
/* @__PURE__ */
|
|
7762
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7763
|
+
/* @__PURE__ */ jsx9(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx9(
|
|
6992
7764
|
InterimButtonsView,
|
|
6993
7765
|
{
|
|
6994
7766
|
onButtonClick,
|
|
@@ -7008,27 +7780,11 @@ function FloPayCheckout({
|
|
|
7008
7780
|
] });
|
|
7009
7781
|
}
|
|
7010
7782
|
if (isPaypalOnlySession && session && directPaypalConfig) {
|
|
7011
|
-
return /* @__PURE__ */
|
|
7012
|
-
/* @__PURE__ */
|
|
7013
|
-
modeError && /* @__PURE__ */
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
role: "alert",
|
|
7017
|
-
"data-testid": "flopay-error",
|
|
7018
|
-
style: {
|
|
7019
|
-
padding: "0.625rem 0.875rem",
|
|
7020
|
-
background: "#FEF2F2",
|
|
7021
|
-
border: "1px solid #FECACA",
|
|
7022
|
-
borderRadius: "8px",
|
|
7023
|
-
color: "#991B1B",
|
|
7024
|
-
fontSize: "0.85rem",
|
|
7025
|
-
fontWeight: 600
|
|
7026
|
-
},
|
|
7027
|
-
children: modeError
|
|
7028
|
-
}
|
|
7029
|
-
),
|
|
7030
|
-
/* @__PURE__ */ jsx8(
|
|
7031
|
-
DirectPayPalButton,
|
|
7783
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7784
|
+
/* @__PURE__ */ jsx9(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsxs6("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
7785
|
+
modeError && /* @__PURE__ */ jsx9(ErrorBanner, { icon: false, children: modeError }),
|
|
7786
|
+
/* @__PURE__ */ jsx9(
|
|
7787
|
+
InstrumentedDirectPayPalButton,
|
|
7032
7788
|
{
|
|
7033
7789
|
sessionId: activeSessionId,
|
|
7034
7790
|
nonce: session.clientSecret || void 0,
|
|
@@ -7043,6 +7799,8 @@ function FloPayCheckout({
|
|
|
7043
7799
|
onDecline,
|
|
7044
7800
|
onButtonClick,
|
|
7045
7801
|
session,
|
|
7802
|
+
telemetry,
|
|
7803
|
+
telemetryContext: telemetryCheckoutContext,
|
|
7046
7804
|
debug
|
|
7047
7805
|
}
|
|
7048
7806
|
)
|
|
@@ -7051,12 +7809,12 @@ function FloPayCheckout({
|
|
|
7051
7809
|
] });
|
|
7052
7810
|
}
|
|
7053
7811
|
if (!flopay || !providerOptions) {
|
|
7054
|
-
return /* @__PURE__ */
|
|
7812
|
+
return /* @__PURE__ */ jsx9(Fragment3, { children: modeOverlay });
|
|
7055
7813
|
}
|
|
7056
7814
|
if (currentMode === "confirm") {
|
|
7057
|
-
return /* @__PURE__ */
|
|
7058
|
-
/* @__PURE__ */
|
|
7059
|
-
modeError && /* @__PURE__ */
|
|
7815
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7816
|
+
/* @__PURE__ */ jsx9(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx9(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ jsxs6("div", { className, children: [
|
|
7817
|
+
modeError && /* @__PURE__ */ jsx9(
|
|
7060
7818
|
"div",
|
|
7061
7819
|
{
|
|
7062
7820
|
style: {
|
|
@@ -7071,7 +7829,7 @@ function FloPayCheckout({
|
|
|
7071
7829
|
renderConfirmButton ? renderConfirmButton({
|
|
7072
7830
|
onConfirm: handleConfirmCheckout,
|
|
7073
7831
|
isProcessing: confirmProcessing
|
|
7074
|
-
}) : /* @__PURE__ */
|
|
7832
|
+
}) : /* @__PURE__ */ jsx9(
|
|
7075
7833
|
"button",
|
|
7076
7834
|
{
|
|
7077
7835
|
type: "button",
|
|
@@ -7096,9 +7854,9 @@ function FloPayCheckout({
|
|
|
7096
7854
|
modeOverlay
|
|
7097
7855
|
] });
|
|
7098
7856
|
}
|
|
7099
|
-
return /* @__PURE__ */
|
|
7100
|
-
/* @__PURE__ */
|
|
7101
|
-
modeError && /* @__PURE__ */
|
|
7857
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7858
|
+
/* @__PURE__ */ jsx9(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx9(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
7859
|
+
modeError && /* @__PURE__ */ jsx9(
|
|
7102
7860
|
"div",
|
|
7103
7861
|
{
|
|
7104
7862
|
style: {
|
|
@@ -7113,7 +7871,7 @@ function FloPayCheckout({
|
|
|
7113
7871
|
children: modeError
|
|
7114
7872
|
}
|
|
7115
7873
|
),
|
|
7116
|
-
/* @__PURE__ */
|
|
7874
|
+
/* @__PURE__ */ jsx9(
|
|
7117
7875
|
SessionInjector,
|
|
7118
7876
|
{
|
|
7119
7877
|
sessionId: activeSessionId,
|
|
@@ -7123,7 +7881,7 @@ function FloPayCheckout({
|
|
|
7123
7881
|
children
|
|
7124
7882
|
}
|
|
7125
7883
|
)
|
|
7126
|
-
] }) : /* @__PURE__ */
|
|
7884
|
+
] }) : /* @__PURE__ */ jsx9(
|
|
7127
7885
|
SplitCardForm,
|
|
7128
7886
|
{
|
|
7129
7887
|
sessionId: activeSessionId,
|
|
@@ -7186,8 +7944,8 @@ function SessionInjector({
|
|
|
7186
7944
|
session,
|
|
7187
7945
|
children
|
|
7188
7946
|
}) {
|
|
7189
|
-
return /* @__PURE__ */
|
|
7190
|
-
if (!
|
|
7947
|
+
return /* @__PURE__ */ jsx9(Fragment3, { children: React9.Children.map(children, (child) => {
|
|
7948
|
+
if (!React9.isValidElement(child)) return child;
|
|
7191
7949
|
const existing = child.props;
|
|
7192
7950
|
const injected = {};
|
|
7193
7951
|
if (!existing.sessionId) injected.sessionId = sessionId;
|
|
@@ -7202,15 +7960,11 @@ function SessionInjector({
|
|
|
7202
7960
|
injected.lastName = session.customer.lastName;
|
|
7203
7961
|
}
|
|
7204
7962
|
if (Object.keys(injected).length === 0) return child;
|
|
7205
|
-
return
|
|
7963
|
+
return React9.cloneElement(child, injected);
|
|
7206
7964
|
}) });
|
|
7207
7965
|
}
|
|
7208
7966
|
function InterimButtonsView({
|
|
7209
7967
|
onButtonClick,
|
|
7210
|
-
onCardButtonClick,
|
|
7211
|
-
cardLoading = false,
|
|
7212
|
-
cardOpen,
|
|
7213
|
-
errorMessage,
|
|
7214
7968
|
showPayPal,
|
|
7215
7969
|
showStripe = true,
|
|
7216
7970
|
showApplePay,
|
|
@@ -7223,12 +7977,6 @@ function InterimButtonsView({
|
|
|
7223
7977
|
cardTitleContent
|
|
7224
7978
|
}) {
|
|
7225
7979
|
const [showCardForm, setShowCardForm] = useState4(false);
|
|
7226
|
-
const isCardOpenControlled = typeof cardOpen === "boolean";
|
|
7227
|
-
useEffect6(() => {
|
|
7228
|
-
if (isCardOpenControlled) {
|
|
7229
|
-
setShowCardForm(cardOpen);
|
|
7230
|
-
}
|
|
7231
|
-
}, [cardOpen, isCardOpenControlled]);
|
|
7232
7980
|
const themeBundle = useMemo4(() => resolveTheme2(theme), [theme]);
|
|
7233
7981
|
const bStyles = useMemo4(() => {
|
|
7234
7982
|
const base = themeBundle?.buttonsLayout ?? resolveButtonsLayoutTheme2(buttonsTheme);
|
|
@@ -7245,7 +7993,7 @@ function InterimButtonsView({
|
|
|
7245
7993
|
};
|
|
7246
7994
|
}, [themeBundle, buttonsTheme, stylesOverride]);
|
|
7247
7995
|
const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
|
|
7248
|
-
const skeleton = (h) => /* @__PURE__ */
|
|
7996
|
+
const skeleton = (h) => /* @__PURE__ */ jsx9("div", { style: {
|
|
7249
7997
|
height: h,
|
|
7250
7998
|
borderRadius: skeletonRadius,
|
|
7251
7999
|
background: "#e5e7eb",
|
|
@@ -7257,25 +8005,20 @@ function InterimButtonsView({
|
|
|
7257
8005
|
const inputBg = bStyles.cardInputBackground ?? "white";
|
|
7258
8006
|
const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
|
|
7259
8007
|
const hideTitle = isEmptySlotContent(cardTitleContent);
|
|
7260
|
-
return /* @__PURE__ */
|
|
8008
|
+
return /* @__PURE__ */ jsxs6("div", { style: {
|
|
7261
8009
|
backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
|
|
7262
8010
|
borderRadius: "8px",
|
|
7263
8011
|
animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
|
|
7264
8012
|
overflow: "hidden",
|
|
7265
8013
|
...bStyles.cardFormContainer
|
|
7266
8014
|
}, children: [
|
|
7267
|
-
/* @__PURE__ */
|
|
7268
|
-
/* @__PURE__ */
|
|
8015
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
|
|
8016
|
+
/* @__PURE__ */ jsxs6(
|
|
7269
8017
|
"button",
|
|
7270
8018
|
{
|
|
7271
8019
|
type: "button",
|
|
7272
|
-
onClick: () =>
|
|
7273
|
-
if (!isCardOpenControlled) {
|
|
7274
|
-
setShowCardForm(false);
|
|
7275
|
-
}
|
|
7276
|
-
},
|
|
8020
|
+
onClick: () => setShowCardForm(false),
|
|
7277
8021
|
"aria-label": "Back to payment methods",
|
|
7278
|
-
disabled: isCardOpenControlled || cardLoading,
|
|
7279
8022
|
style: {
|
|
7280
8023
|
display: "inline-flex",
|
|
7281
8024
|
alignItems: "center",
|
|
@@ -7287,12 +8030,12 @@ function InterimButtonsView({
|
|
|
7287
8030
|
fontWeight: 500,
|
|
7288
8031
|
padding: 0,
|
|
7289
8032
|
flexShrink: 0,
|
|
7290
|
-
opacity:
|
|
7291
|
-
cursor:
|
|
8033
|
+
opacity: 1,
|
|
8034
|
+
cursor: "pointer",
|
|
7292
8035
|
...bStyles.backButton
|
|
7293
8036
|
},
|
|
7294
8037
|
children: [
|
|
7295
|
-
/* @__PURE__ */
|
|
8038
|
+
/* @__PURE__ */ jsx9("span", { style: {
|
|
7296
8039
|
display: "inline-flex",
|
|
7297
8040
|
alignItems: "center",
|
|
7298
8041
|
justifyContent: "center",
|
|
@@ -7301,12 +8044,12 @@ function InterimButtonsView({
|
|
|
7301
8044
|
borderRadius: "50%",
|
|
7302
8045
|
backgroundColor: "#f3f4f6",
|
|
7303
8046
|
...bStyles.backButtonIcon
|
|
7304
|
-
}, children: /* @__PURE__ */
|
|
7305
|
-
/* @__PURE__ */
|
|
8047
|
+
}, children: /* @__PURE__ */ jsx9("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx9("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
8048
|
+
/* @__PURE__ */ jsx9(BackButtonContentSlot, { content: cardBackButtonContent })
|
|
7306
8049
|
]
|
|
7307
8050
|
}
|
|
7308
8051
|
),
|
|
7309
|
-
hideTitle ? /* @__PURE__ */
|
|
8052
|
+
hideTitle ? /* @__PURE__ */ jsx9("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx9("div", { style: {
|
|
7310
8053
|
flex: 1,
|
|
7311
8054
|
textAlign: "center",
|
|
7312
8055
|
fontWeight: 600,
|
|
@@ -7314,11 +8057,11 @@ function InterimButtonsView({
|
|
|
7314
8057
|
color: "#262833",
|
|
7315
8058
|
paddingRight: 80,
|
|
7316
8059
|
...bStyles.title
|
|
7317
|
-
}, children: /* @__PURE__ */
|
|
8060
|
+
}, children: /* @__PURE__ */ jsx9(TitleContentSlot, { content: cardTitleContent }) })
|
|
7318
8061
|
] }),
|
|
7319
|
-
/* @__PURE__ */
|
|
7320
|
-
/* @__PURE__ */
|
|
7321
|
-
/* @__PURE__ */
|
|
8062
|
+
/* @__PURE__ */ jsx9("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx9("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
8063
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex" }, children: [
|
|
8064
|
+
/* @__PURE__ */ jsx9("div", { style: {
|
|
7322
8065
|
flex: 1,
|
|
7323
8066
|
backgroundColor: inputBg,
|
|
7324
8067
|
borderTop: "none",
|
|
@@ -7328,8 +8071,8 @@ function InterimButtonsView({
|
|
|
7328
8071
|
borderBottomLeftRadius: 8,
|
|
7329
8072
|
padding: 12,
|
|
7330
8073
|
height: 45
|
|
7331
|
-
}, children: /* @__PURE__ */
|
|
7332
|
-
/* @__PURE__ */
|
|
8074
|
+
}, children: /* @__PURE__ */ jsx9("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
8075
|
+
/* @__PURE__ */ jsx9("div", { style: {
|
|
7333
8076
|
flex: 1,
|
|
7334
8077
|
backgroundColor: inputBg,
|
|
7335
8078
|
borderTop: "none",
|
|
@@ -7339,10 +8082,10 @@ function InterimButtonsView({
|
|
|
7339
8082
|
borderBottomRightRadius: 8,
|
|
7340
8083
|
padding: 12,
|
|
7341
8084
|
height: 45
|
|
7342
|
-
}, children: /* @__PURE__ */
|
|
8085
|
+
}, children: /* @__PURE__ */ jsx9("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
7343
8086
|
] }),
|
|
7344
|
-
/* @__PURE__ */
|
|
7345
|
-
/* @__PURE__ */
|
|
8087
|
+
/* @__PURE__ */ jsx9("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx9("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
8088
|
+
/* @__PURE__ */ jsx9("div", { style: {
|
|
7346
8089
|
height: 50,
|
|
7347
8090
|
borderRadius: 8,
|
|
7348
8091
|
marginTop: 16,
|
|
@@ -7351,7 +8094,7 @@ function InterimButtonsView({
|
|
|
7351
8094
|
...bStyles.submitButton,
|
|
7352
8095
|
opacity: 0.5
|
|
7353
8096
|
} }),
|
|
7354
|
-
/* @__PURE__ */
|
|
8097
|
+
/* @__PURE__ */ jsx9("style", { children: `
|
|
7355
8098
|
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
7356
8099
|
@keyframes flopay-interim-expand {
|
|
7357
8100
|
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
@@ -7361,23 +8104,17 @@ function InterimButtonsView({
|
|
|
7361
8104
|
` })
|
|
7362
8105
|
] });
|
|
7363
8106
|
}
|
|
7364
|
-
return /* @__PURE__ */
|
|
8107
|
+
return /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
7365
8108
|
showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
7366
8109
|
showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
|
|
7367
|
-
showStripe && /* @__PURE__ */
|
|
8110
|
+
showStripe && /* @__PURE__ */ jsx9(
|
|
7368
8111
|
"button",
|
|
7369
8112
|
{
|
|
7370
8113
|
type: "button",
|
|
7371
|
-
onClick:
|
|
7372
|
-
if (cardLoading) return;
|
|
7373
|
-
if (onCardButtonClick) {
|
|
7374
|
-
await onCardButtonClick();
|
|
7375
|
-
return;
|
|
7376
|
-
}
|
|
8114
|
+
onClick: () => {
|
|
7377
8115
|
onButtonClick?.("card");
|
|
7378
8116
|
setShowCardForm(true);
|
|
7379
8117
|
},
|
|
7380
|
-
disabled: cardLoading,
|
|
7381
8118
|
style: {
|
|
7382
8119
|
width: "100%",
|
|
7383
8120
|
...cardButtonSizing,
|
|
@@ -7387,7 +8124,7 @@ function InterimButtonsView({
|
|
|
7387
8124
|
borderRadius: "8px",
|
|
7388
8125
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
7389
8126
|
fontWeight: 600,
|
|
7390
|
-
cursor:
|
|
8127
|
+
cursor: "pointer",
|
|
7391
8128
|
display: "flex",
|
|
7392
8129
|
alignItems: "center",
|
|
7393
8130
|
justifyContent: "center",
|
|
@@ -7395,7 +8132,7 @@ function InterimButtonsView({
|
|
|
7395
8132
|
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
7396
8133
|
transition: "transform 0.1s",
|
|
7397
8134
|
position: "relative",
|
|
7398
|
-
opacity:
|
|
8135
|
+
opacity: 1,
|
|
7399
8136
|
...bStyles.cardButton
|
|
7400
8137
|
},
|
|
7401
8138
|
onMouseDown: (e) => {
|
|
@@ -7404,39 +8141,22 @@ function InterimButtonsView({
|
|
|
7404
8141
|
onMouseUp: (e) => {
|
|
7405
8142
|
e.currentTarget.style.transform = "scale(1)";
|
|
7406
8143
|
},
|
|
7407
|
-
children: /* @__PURE__ */
|
|
8144
|
+
children: /* @__PURE__ */ jsx9(CardButtonContentSlot, { content: cardButtonContent })
|
|
7408
8145
|
}
|
|
7409
8146
|
),
|
|
7410
|
-
|
|
7411
|
-
margin: "0.25rem 0",
|
|
7412
|
-
padding: "0.625rem 0.875rem",
|
|
7413
|
-
background: "#FEF2F2",
|
|
7414
|
-
border: "1px solid #FECACA",
|
|
7415
|
-
borderRadius: "8px",
|
|
7416
|
-
color: "#991B1B",
|
|
7417
|
-
fontSize: "0.85rem",
|
|
7418
|
-
fontWeight: 600,
|
|
7419
|
-
display: "flex",
|
|
7420
|
-
alignItems: "center",
|
|
7421
|
-
gap: "0.5rem",
|
|
7422
|
-
...bStyles.errorBanner
|
|
7423
|
-
}, children: [
|
|
7424
|
-
/* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx8("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
7425
|
-
errorMessage
|
|
7426
|
-
] }),
|
|
7427
|
-
/* @__PURE__ */ jsx8("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
8147
|
+
/* @__PURE__ */ jsx9("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
7428
8148
|
] });
|
|
7429
8149
|
}
|
|
7430
8150
|
|
|
7431
8151
|
// src/checkout-form.tsx
|
|
7432
8152
|
import { PaymentAPI as PaymentAPI5 } from "@flopay/js";
|
|
7433
8153
|
import { FloPayError as FloPayError6 } from "@flopay/shared";
|
|
7434
|
-
import { forwardRef as forwardRef2, useCallback as
|
|
7435
|
-
import { Fragment as Fragment4, jsx as
|
|
8154
|
+
import { forwardRef as forwardRef2, useCallback as useCallback5, useEffect as useEffect7, useImperativeHandle as useImperativeHandle2, useState as useState5 } from "react";
|
|
8155
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
7436
8156
|
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
7437
8157
|
var CheckoutForm = forwardRef2(
|
|
7438
8158
|
function CheckoutForm2(props, ref) {
|
|
7439
|
-
return /* @__PURE__ */
|
|
8159
|
+
return /* @__PURE__ */ jsx10(CheckoutFormInner, { ...props, innerRef: ref });
|
|
7440
8160
|
}
|
|
7441
8161
|
);
|
|
7442
8162
|
function CheckoutFormInner({
|
|
@@ -7473,20 +8193,20 @@ function CheckoutFormInner({
|
|
|
7473
8193
|
const isSubmitting = externalProcessing ?? processing;
|
|
7474
8194
|
const isSelfContained = !onTokenizedBody;
|
|
7475
8195
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
7476
|
-
const updateError =
|
|
8196
|
+
const updateError = useCallback5(
|
|
7477
8197
|
(err) => {
|
|
7478
8198
|
setError(err);
|
|
7479
8199
|
onErrorChange?.(err);
|
|
7480
8200
|
},
|
|
7481
8201
|
[onErrorChange]
|
|
7482
8202
|
);
|
|
7483
|
-
const emitDecline =
|
|
8203
|
+
const emitDecline = useCallback5(
|
|
7484
8204
|
(input, overrides) => {
|
|
7485
8205
|
onDecline?.(buildDeclineEvent("card", input, overrides));
|
|
7486
8206
|
},
|
|
7487
8207
|
[onDecline]
|
|
7488
8208
|
);
|
|
7489
|
-
const processPaymentInternal =
|
|
8209
|
+
const processPaymentInternal = useCallback5(
|
|
7490
8210
|
async (tokenizedBody, completionPaymentMethodId) => {
|
|
7491
8211
|
setProcessing(true);
|
|
7492
8212
|
updateError(null);
|
|
@@ -7598,7 +8318,7 @@ function CheckoutFormInner({
|
|
|
7598
8318
|
},
|
|
7599
8319
|
[baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
|
|
7600
8320
|
);
|
|
7601
|
-
const dispatchTokenizedBody =
|
|
8321
|
+
const dispatchTokenizedBody = useCallback5(
|
|
7602
8322
|
(tokenizedBody) => {
|
|
7603
8323
|
if (onTokenizedBody) {
|
|
7604
8324
|
onTokenizedBody(tokenizedBody);
|
|
@@ -7653,7 +8373,7 @@ function CheckoutFormInner({
|
|
|
7653
8373
|
localStorage.removeItem(WALLET_RESUME_KEY);
|
|
7654
8374
|
}
|
|
7655
8375
|
}, [sessionId, dispatchTokenizedBody]);
|
|
7656
|
-
const handleSubmit =
|
|
8376
|
+
const handleSubmit = useCallback5(
|
|
7657
8377
|
async (e) => {
|
|
7658
8378
|
e.preventDefault();
|
|
7659
8379
|
if (!flopay || !elements || isSubmitting) return;
|
|
@@ -7679,8 +8399,7 @@ function CheckoutFormInner({
|
|
|
7679
8399
|
if (!sessionId || !email) {
|
|
7680
8400
|
throw new FloPayError6("Missing sessionId or email", "validation_error");
|
|
7681
8401
|
}
|
|
7682
|
-
const intentHeaders =
|
|
7683
|
-
if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
|
|
8402
|
+
const intentHeaders = intentRequestHeaders(nonce);
|
|
7684
8403
|
const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
|
|
7685
8404
|
method: "POST",
|
|
7686
8405
|
headers: intentHeaders,
|
|
@@ -7745,8 +8464,8 @@ function CheckoutFormInner({
|
|
|
7745
8464
|
[flopay, elements, isSubmitting, sessionId, nonce, email, firstName, lastName, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
|
|
7746
8465
|
);
|
|
7747
8466
|
const isReady = flopay !== null && elements !== null;
|
|
7748
|
-
return /* @__PURE__ */
|
|
7749
|
-
(is3DSActive || isSubmitting) && /* @__PURE__ */
|
|
8467
|
+
return /* @__PURE__ */ jsxs7("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
8468
|
+
(is3DSActive || isSubmitting) && /* @__PURE__ */ jsx10("div", { "data-testid": "flopay-overlay", style: {
|
|
7750
8469
|
position: "absolute",
|
|
7751
8470
|
inset: 0,
|
|
7752
8471
|
background: "rgba(255,255,255,0.7)",
|
|
@@ -7755,12 +8474,12 @@ function CheckoutFormInner({
|
|
|
7755
8474
|
justifyContent: "center",
|
|
7756
8475
|
zIndex: 10
|
|
7757
8476
|
}, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
|
|
7758
|
-
!isReady && /* @__PURE__ */
|
|
7759
|
-
isReady && /* @__PURE__ */
|
|
7760
|
-
/* @__PURE__ */
|
|
7761
|
-
showAddress && /* @__PURE__ */
|
|
7762
|
-
displayError && /* @__PURE__ */
|
|
7763
|
-
children ?? /* @__PURE__ */
|
|
8477
|
+
!isReady && /* @__PURE__ */ jsx10("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
|
|
8478
|
+
isReady && /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
8479
|
+
/* @__PURE__ */ jsx10(PaymentElement, { options: { layout } }),
|
|
8480
|
+
showAddress && /* @__PURE__ */ jsx10(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
|
|
8481
|
+
displayError && /* @__PURE__ */ jsx10("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
|
|
8482
|
+
children ?? /* @__PURE__ */ jsx10(
|
|
7764
8483
|
"button",
|
|
7765
8484
|
{
|
|
7766
8485
|
type: "submit",
|
|
@@ -7776,8 +8495,8 @@ function CheckoutFormInner({
|
|
|
7776
8495
|
// src/paypal-button.tsx
|
|
7777
8496
|
import { PaymentAPI as PaymentAPI6 } from "@flopay/js";
|
|
7778
8497
|
import { FloPayError as FloPayError7 } from "@flopay/shared";
|
|
7779
|
-
import { useCallback as
|
|
7780
|
-
import { Fragment as Fragment5, jsx as
|
|
8498
|
+
import { useCallback as useCallback6, useEffect as useEffect8, useRef as useRef7, useState as useState6 } from "react";
|
|
8499
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
7781
8500
|
function PayPalButton({
|
|
7782
8501
|
sessionId,
|
|
7783
8502
|
nonce,
|
|
@@ -7797,9 +8516,9 @@ function PayPalButton({
|
|
|
7797
8516
|
const contextBillingUrl = useBillingApiUrl();
|
|
7798
8517
|
const [ready, setReady] = useState6(false);
|
|
7799
8518
|
const [submitting, setSubmitting] = useState6(false);
|
|
7800
|
-
const paypalResumeAttempted =
|
|
8519
|
+
const paypalResumeAttempted = useRef7(false);
|
|
7801
8520
|
const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
|
|
7802
|
-
const processPaymentInternal =
|
|
8521
|
+
const processPaymentInternal = useCallback6(
|
|
7803
8522
|
async (tokenizedBody) => {
|
|
7804
8523
|
try {
|
|
7805
8524
|
const api = new PaymentAPI6(baseUrl);
|
|
@@ -7827,7 +8546,7 @@ function PayPalButton({
|
|
|
7827
8546
|
},
|
|
7828
8547
|
[baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
|
|
7829
8548
|
);
|
|
7830
|
-
const dispatchTokenizedBody =
|
|
8549
|
+
const dispatchTokenizedBody = useCallback6(
|
|
7831
8550
|
(body) => {
|
|
7832
8551
|
if (onTokenizedBody) {
|
|
7833
8552
|
onTokenizedBody(body);
|
|
@@ -7885,7 +8604,7 @@ function PayPalButton({
|
|
|
7885
8604
|
}
|
|
7886
8605
|
})();
|
|
7887
8606
|
}, [flopay, dispatchTokenizedBody, onErrorChange]);
|
|
7888
|
-
const handlePayPalConfirm =
|
|
8607
|
+
const handlePayPalConfirm = useCallback6(async () => {
|
|
7889
8608
|
if (!flopay || !elements) return;
|
|
7890
8609
|
try {
|
|
7891
8610
|
setSubmitting(true);
|
|
@@ -7919,11 +8638,11 @@ function PayPalButton({
|
|
|
7919
8638
|
}
|
|
7920
8639
|
}, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
|
|
7921
8640
|
if (!flopay || !elements) {
|
|
7922
|
-
return /* @__PURE__ */
|
|
8641
|
+
return /* @__PURE__ */ jsx11("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
|
|
7923
8642
|
}
|
|
7924
|
-
return /* @__PURE__ */
|
|
7925
|
-
!ready && /* @__PURE__ */
|
|
7926
|
-
/* @__PURE__ */
|
|
8643
|
+
return /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
8644
|
+
!ready && /* @__PURE__ */ jsx11("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
|
|
8645
|
+
/* @__PURE__ */ jsx11("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ jsx11(
|
|
7927
8646
|
"button",
|
|
7928
8647
|
{
|
|
7929
8648
|
type: "button",
|
|
@@ -7945,7 +8664,7 @@ function PayPalButton({
|
|
|
7945
8664
|
children: submitting ? "Processing..." : "PayPal"
|
|
7946
8665
|
}
|
|
7947
8666
|
) }),
|
|
7948
|
-
(submitting || isProcessing) && /* @__PURE__ */
|
|
8667
|
+
(submitting || isProcessing) && /* @__PURE__ */ jsx11("div", { style: {
|
|
7949
8668
|
position: "fixed",
|
|
7950
8669
|
inset: 0,
|
|
7951
8670
|
background: "rgba(0,0,0,0.4)",
|
|
@@ -7953,7 +8672,7 @@ function PayPalButton({
|
|
|
7953
8672
|
alignItems: "center",
|
|
7954
8673
|
justifyContent: "center",
|
|
7955
8674
|
zIndex: 1e3
|
|
7956
|
-
}, children: /* @__PURE__ */
|
|
8675
|
+
}, children: /* @__PURE__ */ jsx11("div", { style: {
|
|
7957
8676
|
background: "white",
|
|
7958
8677
|
borderRadius: 8,
|
|
7959
8678
|
padding: "1.5rem",
|
|
@@ -7965,10 +8684,10 @@ function PayPalButton({
|
|
|
7965
8684
|
}
|
|
7966
8685
|
|
|
7967
8686
|
// src/automatic-payment-button.tsx
|
|
7968
|
-
import { useCallback as
|
|
8687
|
+
import { useCallback as useCallback7, useEffect as useEffect9, useMemo as useMemo5, useRef as useRef8, useState as useState7 } from "react";
|
|
7969
8688
|
import { PaymentAPI as PaymentAPI7 } from "@flopay/js";
|
|
7970
8689
|
import { FloPayError as FloPayError8, resolveBillingApiUrl as resolveBillingApiUrl4, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme3, resolveTheme as resolveTheme3 } from "@flopay/shared";
|
|
7971
|
-
import { Fragment as Fragment6, jsx as
|
|
8690
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
7972
8691
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
|
|
7973
8692
|
function sleep2(ms) {
|
|
7974
8693
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -8084,12 +8803,12 @@ function FloPayAutomaticPaymentButton({
|
|
|
8084
8803
|
const [overlayStatus, setOverlayStatus] = useState7(null);
|
|
8085
8804
|
const [overlayError, setOverlayError] = useState7(null);
|
|
8086
8805
|
const [fallbackSession, setFallbackSession] = useState7(null);
|
|
8087
|
-
const isMountedRef =
|
|
8088
|
-
const threeDsAbortRef =
|
|
8089
|
-
const fallbackSessionRef =
|
|
8090
|
-
const onSuccessRef =
|
|
8091
|
-
const onErrorRef =
|
|
8092
|
-
const onDeclineRef =
|
|
8806
|
+
const isMountedRef = useRef8(true);
|
|
8807
|
+
const threeDsAbortRef = useRef8(null);
|
|
8808
|
+
const fallbackSessionRef = useRef8(fallbackSession);
|
|
8809
|
+
const onSuccessRef = useRef8(onSuccess);
|
|
8810
|
+
const onErrorRef = useRef8(onError);
|
|
8811
|
+
const onDeclineRef = useRef8(onDecline);
|
|
8093
8812
|
useEffect9(() => {
|
|
8094
8813
|
fallbackSessionRef.current = fallbackSession;
|
|
8095
8814
|
}, [fallbackSession]);
|
|
@@ -8110,7 +8829,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8110
8829
|
};
|
|
8111
8830
|
}, []);
|
|
8112
8831
|
useEffect9(() => {
|
|
8113
|
-
if (
|
|
8832
|
+
if (typeof window === "undefined") {
|
|
8114
8833
|
return;
|
|
8115
8834
|
}
|
|
8116
8835
|
const handleKeyDown = (event) => {
|
|
@@ -8122,14 +8841,14 @@ function FloPayAutomaticPaymentButton({
|
|
|
8122
8841
|
return () => {
|
|
8123
8842
|
window.removeEventListener("keydown", handleKeyDown);
|
|
8124
8843
|
};
|
|
8125
|
-
}, [
|
|
8126
|
-
const emitDecline =
|
|
8844
|
+
}, []);
|
|
8845
|
+
const emitDecline = useCallback7((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
|
|
8127
8846
|
onDeclineRef.current?.(buildDeclineEvent(method, error, {
|
|
8128
8847
|
code: error.code,
|
|
8129
8848
|
declineCode: error.declineCode
|
|
8130
8849
|
}));
|
|
8131
8850
|
}, []);
|
|
8132
|
-
const showSuccess =
|
|
8851
|
+
const showSuccess = useCallback7(async (event) => {
|
|
8133
8852
|
if (!isMountedRef.current) return;
|
|
8134
8853
|
setOverlayError(null);
|
|
8135
8854
|
setOverlayStatus("success");
|
|
@@ -8137,7 +8856,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8137
8856
|
if (!isMountedRef.current) return;
|
|
8138
8857
|
onSuccessRef.current?.(event);
|
|
8139
8858
|
}, []);
|
|
8140
|
-
const showError =
|
|
8859
|
+
const showError = useCallback7(async (error, options) => {
|
|
8141
8860
|
if (!isMountedRef.current) return;
|
|
8142
8861
|
onErrorRef.current?.(error);
|
|
8143
8862
|
if (options?.emitDecline) {
|
|
@@ -8147,7 +8866,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8147
8866
|
setOverlayStatus("error");
|
|
8148
8867
|
await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
|
|
8149
8868
|
}, [emitDecline]);
|
|
8150
|
-
const processResolvedSession =
|
|
8869
|
+
const processResolvedSession = useCallback7(async (apiResult, resolvedSessionId, options) => {
|
|
8151
8870
|
const session = apiResult.data.session ?? null;
|
|
8152
8871
|
if (!session) {
|
|
8153
8872
|
throw new FloPayError8("No session data returned", "api_error");
|
|
@@ -8303,7 +9022,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8303
9022
|
showError,
|
|
8304
9023
|
showSuccess
|
|
8305
9024
|
]);
|
|
8306
|
-
const handleButtonClick =
|
|
9025
|
+
const handleButtonClick = useCallback7(async (event) => {
|
|
8307
9026
|
buttonProps.onClick?.(event);
|
|
8308
9027
|
if (event.defaultPrevented || disabled || isProcessing) {
|
|
8309
9028
|
return;
|
|
@@ -8385,7 +9104,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8385
9104
|
showError,
|
|
8386
9105
|
showSuccess
|
|
8387
9106
|
]);
|
|
8388
|
-
const handleFallbackComplete =
|
|
9107
|
+
const handleFallbackComplete = useCallback7((result) => {
|
|
8389
9108
|
const activeFallback = fallbackSessionRef.current;
|
|
8390
9109
|
setFallbackSession(null);
|
|
8391
9110
|
onSuccessRef.current?.({
|
|
@@ -8395,10 +9114,10 @@ function FloPayAutomaticPaymentButton({
|
|
|
8395
9114
|
autoCompleted: false
|
|
8396
9115
|
});
|
|
8397
9116
|
}, []);
|
|
8398
|
-
const handleFallbackError =
|
|
9117
|
+
const handleFallbackError = useCallback7((error) => {
|
|
8399
9118
|
onErrorRef.current?.(error);
|
|
8400
9119
|
}, []);
|
|
8401
|
-
const handleFallbackDecline =
|
|
9120
|
+
const handleFallbackDecline = useCallback7((decline) => {
|
|
8402
9121
|
onDeclineRef.current?.(decline);
|
|
8403
9122
|
}, []);
|
|
8404
9123
|
const themeBundle = useMemo5(() => resolveTheme3(theme), [theme]);
|
|
@@ -8429,8 +9148,8 @@ function FloPayAutomaticPaymentButton({
|
|
|
8429
9148
|
const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
|
|
8430
9149
|
const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
|
|
8431
9150
|
const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
|
|
8432
|
-
return /* @__PURE__ */
|
|
8433
|
-
/* @__PURE__ */
|
|
9151
|
+
return /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
9152
|
+
/* @__PURE__ */ jsx12(
|
|
8434
9153
|
"button",
|
|
8435
9154
|
{
|
|
8436
9155
|
...buttonProps,
|
|
@@ -8494,17 +9213,17 @@ function FloPayAutomaticPaymentButton({
|
|
|
8494
9213
|
e.currentTarget.style.transform = "scale(1)";
|
|
8495
9214
|
}
|
|
8496
9215
|
},
|
|
8497
|
-
children: /* @__PURE__ */
|
|
9216
|
+
children: /* @__PURE__ */ jsx12(CardButtonContentSlot, { content: children })
|
|
8498
9217
|
}
|
|
8499
9218
|
),
|
|
8500
|
-
overlayStatus && /* @__PURE__ */
|
|
9219
|
+
overlayStatus && /* @__PURE__ */ jsx12(
|
|
8501
9220
|
ProcessingOverlay,
|
|
8502
9221
|
{
|
|
8503
9222
|
status: overlayStatus,
|
|
8504
9223
|
errorMessage: overlayError
|
|
8505
9224
|
}
|
|
8506
9225
|
),
|
|
8507
|
-
fallbackSession && /* @__PURE__ */
|
|
9226
|
+
fallbackSession && /* @__PURE__ */ jsx12(
|
|
8508
9227
|
"div",
|
|
8509
9228
|
{
|
|
8510
9229
|
"data-testid": "flopay-automatic-payment-fallback",
|
|
@@ -8525,7 +9244,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8525
9244
|
padding: "1.5rem",
|
|
8526
9245
|
zIndex: 1100
|
|
8527
9246
|
},
|
|
8528
|
-
children: /* @__PURE__ */
|
|
9247
|
+
children: /* @__PURE__ */ jsx12(
|
|
8529
9248
|
"div",
|
|
8530
9249
|
{
|
|
8531
9250
|
style: {
|
|
@@ -8541,7 +9260,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
8541
9260
|
flexDirection: "column",
|
|
8542
9261
|
gap: "1rem"
|
|
8543
9262
|
},
|
|
8544
|
-
children: /* @__PURE__ */
|
|
9263
|
+
children: /* @__PURE__ */ jsx12(
|
|
8545
9264
|
FloPayCheckout,
|
|
8546
9265
|
{
|
|
8547
9266
|
sessionId: fallbackSession.sessionId,
|