@easypayment/medusa-payment-paypal 0.9.20 → 0.9.22
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/.medusa/server/src/admin/index.js +148 -270
- package/.medusa/server/src/admin/index.mjs +148 -270
- package/.medusa/server/src/admin/routes/settings/paypal/connection/page.d.ts.map +1 -1
- package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js +209 -369
- package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js.map +1 -1
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/connection/page.tsx +235 -414
|
@@ -224,9 +224,6 @@ function AdditionalSettingsTab() {
|
|
|
224
224
|
)
|
|
225
225
|
] }) });
|
|
226
226
|
}
|
|
227
|
-
function PayPalApplePayPage() {
|
|
228
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
229
|
-
}
|
|
230
227
|
const DEFAULT_FORM = {
|
|
231
228
|
enabled: true,
|
|
232
229
|
title: "Credit or Debit Card",
|
|
@@ -311,6 +308,12 @@ function AdvancedCardPaymentsTab() {
|
|
|
311
308
|
)
|
|
312
309
|
] }) });
|
|
313
310
|
}
|
|
311
|
+
function PayPalApplePayPage() {
|
|
312
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
313
|
+
}
|
|
314
|
+
function PayPalGooglePayPage() {
|
|
315
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
316
|
+
}
|
|
314
317
|
const config = adminSdk.defineRouteConfig({
|
|
315
318
|
label: "PayPal Connection"
|
|
316
319
|
});
|
|
@@ -319,9 +322,9 @@ const PARTNER_JS_URLS = {
|
|
|
319
322
|
live: "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js"
|
|
320
323
|
};
|
|
321
324
|
const SERVICE_URL = "/admin/paypal/onboarding-link";
|
|
322
|
-
const POPUP_NAME = "
|
|
325
|
+
const POPUP_NAME = "PPFrame";
|
|
323
326
|
const CACHE_PREFIX = "pp_onboard_cache";
|
|
324
|
-
const CACHE_EXPIRY =
|
|
327
|
+
const CACHE_EXPIRY = 6 * 60 * 60 * 1e3;
|
|
325
328
|
const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
|
|
326
329
|
const STATUS_ENDPOINT = "/admin/paypal/status";
|
|
327
330
|
const SAVE_CREDENTIALS_ENDPOINT = "/admin/paypal/save-credentials";
|
|
@@ -344,7 +347,9 @@ function readCachedUrl(env) {
|
|
|
344
347
|
function writeCachedUrl(env, url) {
|
|
345
348
|
try {
|
|
346
349
|
localStorage.setItem(cacheKeyFor(env), JSON.stringify({ url, ts: Date.now() }));
|
|
350
|
+
return readCachedUrl(env) === url;
|
|
347
351
|
} catch {
|
|
352
|
+
return false;
|
|
348
353
|
}
|
|
349
354
|
}
|
|
350
355
|
function clearCachedUrl(env) {
|
|
@@ -358,58 +363,12 @@ function clearCachedUrl(env) {
|
|
|
358
363
|
} catch {
|
|
359
364
|
}
|
|
360
365
|
}
|
|
361
|
-
function isPayPalOrigin(origin) {
|
|
362
|
-
try {
|
|
363
|
-
const host = new URL(origin).hostname.toLowerCase();
|
|
364
|
-
return host === "www.paypal.com" || host === "www.sandbox.paypal.com" || host.endsWith(".paypal.com") || host.endsWith(".paypalobjects.com");
|
|
365
|
-
} catch {
|
|
366
|
-
return false;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
function extractAuth(data) {
|
|
370
|
-
if (!data) return {};
|
|
371
|
-
if (typeof data === "object") {
|
|
372
|
-
const obj = data;
|
|
373
|
-
const authCode = obj.authCode ?? obj.auth_code ?? obj.authcode;
|
|
374
|
-
const sharedId = obj.sharedId ?? obj.shared_id ?? obj.sharedid;
|
|
375
|
-
if (authCode && sharedId) {
|
|
376
|
-
return { authCode: String(authCode), sharedId: String(sharedId) };
|
|
377
|
-
}
|
|
378
|
-
for (const key of ["data", "payload", "message", "detail", "body"]) {
|
|
379
|
-
if (obj[key] && typeof obj[key] === "object") {
|
|
380
|
-
const inner = extractAuth(obj[key]);
|
|
381
|
-
if (inner.authCode && inner.sharedId) return inner;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return {};
|
|
385
|
-
}
|
|
386
|
-
if (typeof data === "string") {
|
|
387
|
-
const s = data.trim();
|
|
388
|
-
if (!s) return {};
|
|
389
|
-
if (s.startsWith("{")) {
|
|
390
|
-
try {
|
|
391
|
-
return extractAuth(JSON.parse(s));
|
|
392
|
-
} catch {
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
if (/auth_?code/i.test(s) && /shared_?id/i.test(s)) {
|
|
396
|
-
try {
|
|
397
|
-
const sp = new URLSearchParams(s.replace(/^[?#]/, ""));
|
|
398
|
-
const authCode = sp.get("authCode") || sp.get("auth_code") || void 0;
|
|
399
|
-
const sharedId = sp.get("sharedId") || sp.get("shared_id") || void 0;
|
|
400
|
-
if (authCode && sharedId) return { authCode, sharedId };
|
|
401
|
-
} catch {
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
return {};
|
|
406
|
-
}
|
|
407
366
|
function PayPalConnectionPage() {
|
|
408
367
|
const [env, setEnv] = react.useState("live");
|
|
409
368
|
const [envReady, setEnvReady] = react.useState(false);
|
|
410
369
|
const [connState, setConnState] = react.useState("loading");
|
|
370
|
+
const [partnerReady, setPartnerReady] = react.useState(false);
|
|
411
371
|
const [error, setError] = react.useState(null);
|
|
412
|
-
const [popupBlocked, setPopupBlocked] = react.useState(false);
|
|
413
372
|
const [finalUrl, setFinalUrl] = react.useState("");
|
|
414
373
|
const [showManual, setShowManual] = react.useState(false);
|
|
415
374
|
const [clientId, setClientId] = react.useState("");
|
|
@@ -417,22 +376,12 @@ function PayPalConnectionPage() {
|
|
|
417
376
|
const [statusInfo, setStatusInfo] = react.useState(null);
|
|
418
377
|
const [onboardingInProgress, setOnboardingInProgress] = react.useState(false);
|
|
419
378
|
const initLoaderRef = react.useRef(null);
|
|
420
|
-
const paypalButtonRef = react.useRef(null);
|
|
421
379
|
const errorLogRef = react.useRef(null);
|
|
422
380
|
const runIdRef = react.useRef(0);
|
|
423
381
|
const currentRunId = react.useRef(0);
|
|
424
|
-
const finalUrlRef = react.useRef(finalUrl);
|
|
425
|
-
finalUrlRef.current = finalUrl;
|
|
426
|
-
const connStateRef = react.useRef(connState);
|
|
427
|
-
connStateRef.current = connState;
|
|
428
|
-
const inProgressRef = react.useRef(onboardingInProgress);
|
|
429
|
-
inProgressRef.current = onboardingInProgress;
|
|
430
382
|
const envRef = react.useRef(env);
|
|
431
383
|
envRef.current = env;
|
|
432
|
-
const popupRef = react.useRef(null);
|
|
433
|
-
const popupPollRef = react.useRef(null);
|
|
434
384
|
const completedRef = react.useRef(false);
|
|
435
|
-
const partnerBoundRef = react.useRef(false);
|
|
436
385
|
const ppBtnMeasureRef = react.useRef(null);
|
|
437
386
|
const [ppBtnWidth, setPpBtnWidth] = react.useState(null);
|
|
438
387
|
const canSaveManual = react.useMemo(() => {
|
|
@@ -442,131 +391,23 @@ function PayPalConnectionPage() {
|
|
|
442
391
|
setConnState("error");
|
|
443
392
|
setError(msg);
|
|
444
393
|
}, []);
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const openOnboardingPopup = react.useCallback(
|
|
452
|
-
(url) => {
|
|
453
|
-
const w = 450;
|
|
454
|
-
const h = 600;
|
|
455
|
-
const baseLeft = typeof window.screenX === "number" ? window.screenX : window.screenLeft || 0;
|
|
456
|
-
const baseTop = typeof window.screenY === "number" ? window.screenY : window.screenTop || 0;
|
|
457
|
-
const outerW = window.outerWidth || document.documentElement.clientWidth || 1024;
|
|
458
|
-
const outerH = window.outerHeight || document.documentElement.clientHeight || 768;
|
|
459
|
-
const left = Math.round(baseLeft + Math.max(0, (outerW - w) / 2));
|
|
460
|
-
const top = Math.round(baseTop + Math.max(0, (outerH - h) / 2));
|
|
461
|
-
const features = `popup=yes,width=${w},height=${h},left=${left},top=${top},scrollbars=yes,resizable=yes`;
|
|
462
|
-
let popup = null;
|
|
463
|
-
try {
|
|
464
|
-
popup = window.open(url, POPUP_NAME, features);
|
|
465
|
-
} catch {
|
|
466
|
-
popup = null;
|
|
467
|
-
}
|
|
468
|
-
if (popup) {
|
|
469
|
-
popupRef.current = popup;
|
|
470
|
-
try {
|
|
471
|
-
popup.focus();
|
|
472
|
-
} catch {
|
|
394
|
+
const generateLinkAndReload = react.useCallback(
|
|
395
|
+
async (targetEnv, runId) => {
|
|
396
|
+
if (initLoaderRef.current) {
|
|
397
|
+
const loaderText = initLoaderRef.current.querySelector("#loader-text");
|
|
398
|
+
if (loaderText) {
|
|
399
|
+
loaderText.textContent = "Generating onboarding session...";
|
|
473
400
|
}
|
|
474
|
-
stopPopupPoll();
|
|
475
|
-
popupPollRef.current = setInterval(() => {
|
|
476
|
-
if (!popupRef.current || popupRef.current.closed) {
|
|
477
|
-
stopPopupPoll();
|
|
478
|
-
}
|
|
479
|
-
}, 1e3);
|
|
480
401
|
}
|
|
481
|
-
return popup;
|
|
482
|
-
},
|
|
483
|
-
[stopPopupPoll]
|
|
484
|
-
);
|
|
485
|
-
const completeOnboarding = react.useCallback(
|
|
486
|
-
async (authCode, sharedId) => {
|
|
487
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
488
|
-
if (!authCode || !sharedId) return;
|
|
489
|
-
if (completedRef.current) return;
|
|
490
|
-
completedRef.current = true;
|
|
491
402
|
try {
|
|
492
|
-
|
|
493
|
-
} catch {
|
|
494
|
-
}
|
|
495
|
-
const activeEnv = envRef.current === "sandbox" ? "sandbox" : "live";
|
|
496
|
-
setOnboardingInProgress(true);
|
|
497
|
-
setConnState("loading");
|
|
498
|
-
setError(null);
|
|
499
|
-
setPopupBlocked(false);
|
|
500
|
-
try {
|
|
501
|
-
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
403
|
+
const res = await fetch(SERVICE_URL, {
|
|
502
404
|
method: "POST",
|
|
503
405
|
headers: { "content-type": "application/json" },
|
|
504
406
|
credentials: "include",
|
|
505
|
-
body: JSON.stringify({
|
|
407
|
+
body: JSON.stringify({ products: ["PPCP"], environment: targetEnv })
|
|
506
408
|
});
|
|
507
|
-
if (!res.ok) {
|
|
508
|
-
|
|
509
|
-
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
510
|
-
}
|
|
511
|
-
try {
|
|
512
|
-
(_a = popupRef.current) == null ? void 0 : _a.close();
|
|
513
|
-
} catch {
|
|
514
|
-
}
|
|
515
|
-
stopPopupPoll();
|
|
516
|
-
try {
|
|
517
|
-
const close1 = (_e = (_d = (_c = (_b = window.PAYPAL) == null ? void 0 : _b.apps) == null ? void 0 : _c.Signup) == null ? void 0 : _d.MiniBrowser) == null ? void 0 : _e.closeFlow;
|
|
518
|
-
if (typeof close1 === "function") close1();
|
|
519
|
-
} catch {
|
|
520
|
-
}
|
|
521
|
-
try {
|
|
522
|
-
const close2 = ((_h = (_g = (_f = window.PAYPAL) == null ? void 0 : _f.apps) == null ? void 0 : _g.Signup) == null ? void 0 : _h.miniBrowser) && window.PAYPAL.apps.Signup.miniBrowser.closeFlow;
|
|
523
|
-
if (typeof close2 === "function") close2();
|
|
524
|
-
} catch {
|
|
525
|
-
}
|
|
526
|
-
clearCachedUrl(activeEnv);
|
|
527
|
-
try {
|
|
528
|
-
const statusRes = await fetch(
|
|
529
|
-
`${STATUS_ENDPOINT}?environment=${activeEnv}`,
|
|
530
|
-
{ method: "GET", credentials: "include" }
|
|
531
|
-
);
|
|
532
|
-
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
533
|
-
setStatusInfo(refreshedStatus || null);
|
|
534
|
-
} catch {
|
|
535
|
-
}
|
|
536
|
-
setConnState("connected");
|
|
537
|
-
setShowManual(false);
|
|
538
|
-
} catch (e) {
|
|
539
|
-
completedRef.current = false;
|
|
540
|
-
console.error(e);
|
|
541
|
-
setConnState("error");
|
|
542
|
-
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
543
|
-
} finally {
|
|
544
|
-
setOnboardingInProgress(false);
|
|
545
|
-
}
|
|
546
|
-
},
|
|
547
|
-
[stopPopupPoll]
|
|
548
|
-
);
|
|
549
|
-
const fetchFreshLink = react.useCallback(
|
|
550
|
-
(runId, targetEnv) => {
|
|
551
|
-
if (initLoaderRef.current) {
|
|
552
|
-
const loaderText = initLoaderRef.current.querySelector("#loader-text");
|
|
553
|
-
if (loaderText)
|
|
554
|
-
loaderText.textContent = "Generating onboarding session...";
|
|
555
|
-
}
|
|
556
|
-
fetch(SERVICE_URL, {
|
|
557
|
-
method: "POST",
|
|
558
|
-
headers: { "content-type": "application/json" },
|
|
559
|
-
credentials: "include",
|
|
560
|
-
body: JSON.stringify({
|
|
561
|
-
products: ["PPCP"],
|
|
562
|
-
// Generate the link for the explicitly selected environment so it can
|
|
563
|
-
// never depend on a racing POST /environment having landed yet.
|
|
564
|
-
environment: targetEnv
|
|
565
|
-
})
|
|
566
|
-
}).then((r) => {
|
|
567
|
-
if (!r.ok) throw new Error(`Service returned ${r.status}`);
|
|
568
|
-
return r.json();
|
|
569
|
-
}).then((data) => {
|
|
409
|
+
if (!res.ok) throw new Error(`Service returned ${res.status}`);
|
|
410
|
+
const data = await res.json();
|
|
570
411
|
if (runId !== currentRunId.current) return;
|
|
571
412
|
const href = data == null ? void 0 : data.onboarding_url;
|
|
572
413
|
if (!href) {
|
|
@@ -574,13 +415,17 @@ function PayPalConnectionPage() {
|
|
|
574
415
|
return;
|
|
575
416
|
}
|
|
576
417
|
const url = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
|
|
577
|
-
writeCachedUrl(targetEnv, url);
|
|
418
|
+
const persisted = writeCachedUrl(targetEnv, url);
|
|
419
|
+
if (persisted) {
|
|
420
|
+
window.location.reload();
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
578
423
|
setFinalUrl(url);
|
|
579
424
|
setConnState("ready");
|
|
580
|
-
}
|
|
425
|
+
} catch {
|
|
581
426
|
if (runId !== currentRunId.current) return;
|
|
582
427
|
showError("Unable to connect to service.");
|
|
583
|
-
}
|
|
428
|
+
}
|
|
584
429
|
},
|
|
585
430
|
[showError]
|
|
586
431
|
);
|
|
@@ -597,12 +442,60 @@ function PayPalConnectionPage() {
|
|
|
597
442
|
alive = false;
|
|
598
443
|
};
|
|
599
444
|
}, []);
|
|
445
|
+
react.useEffect(() => {
|
|
446
|
+
if (!envReady) return;
|
|
447
|
+
currentRunId.current = ++runIdRef.current;
|
|
448
|
+
const runId = currentRunId.current;
|
|
449
|
+
let cancelled = false;
|
|
450
|
+
completedRef.current = false;
|
|
451
|
+
const run = async () => {
|
|
452
|
+
setConnState("loading");
|
|
453
|
+
setError(null);
|
|
454
|
+
setFinalUrl("");
|
|
455
|
+
try {
|
|
456
|
+
const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
457
|
+
method: "GET",
|
|
458
|
+
credentials: "include"
|
|
459
|
+
});
|
|
460
|
+
const st = await r.json().catch(() => ({}));
|
|
461
|
+
if (cancelled || runId !== currentRunId.current) return;
|
|
462
|
+
setStatusInfo(st);
|
|
463
|
+
const isConnected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
|
|
464
|
+
if (isConnected) {
|
|
465
|
+
setConnState("connected");
|
|
466
|
+
setShowManual(false);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
} catch (e) {
|
|
470
|
+
console.error(e);
|
|
471
|
+
}
|
|
472
|
+
if (cancelled || runId !== currentRunId.current) return;
|
|
473
|
+
const cached = readCachedUrl(env);
|
|
474
|
+
if (cached) {
|
|
475
|
+
setFinalUrl(cached);
|
|
476
|
+
setConnState("ready");
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
await generateLinkAndReload(env, runId);
|
|
480
|
+
};
|
|
481
|
+
run();
|
|
482
|
+
return () => {
|
|
483
|
+
cancelled = true;
|
|
484
|
+
};
|
|
485
|
+
}, [env, envReady, generateLinkAndReload]);
|
|
600
486
|
react.useEffect(() => {
|
|
601
487
|
var _a, _b, _c;
|
|
602
488
|
if (connState !== "ready" || !finalUrl) return;
|
|
603
489
|
const scriptUrl = PARTNER_JS_URLS[env];
|
|
604
490
|
let cancelled = false;
|
|
605
491
|
let pollTimer;
|
|
492
|
+
setPartnerReady(false);
|
|
493
|
+
const readyFallback = setTimeout(() => {
|
|
494
|
+
if (!cancelled) setPartnerReady(true);
|
|
495
|
+
}, 6e3);
|
|
496
|
+
const markReady = () => {
|
|
497
|
+
if (!cancelled) setPartnerReady(true);
|
|
498
|
+
};
|
|
606
499
|
const initPartner = (attempt = 0) => {
|
|
607
500
|
var _a2, _b2;
|
|
608
501
|
if (cancelled) return;
|
|
@@ -611,19 +504,19 @@ function PayPalConnectionPage() {
|
|
|
611
504
|
if (target == null ? void 0 : target.init) {
|
|
612
505
|
try {
|
|
613
506
|
target.init();
|
|
614
|
-
partnerBoundRef.current = true;
|
|
615
507
|
} catch (e) {
|
|
616
508
|
console.error("[paypal] partner.js init failed:", e);
|
|
617
509
|
}
|
|
510
|
+
markReady();
|
|
618
511
|
return;
|
|
619
512
|
}
|
|
620
513
|
if (typeof (signup == null ? void 0 : signup.render) === "function") {
|
|
621
514
|
try {
|
|
622
515
|
signup.render();
|
|
623
|
-
partnerBoundRef.current = true;
|
|
624
516
|
} catch (e) {
|
|
625
517
|
console.error("[paypal] partner.js render failed:", e);
|
|
626
518
|
}
|
|
519
|
+
markReady();
|
|
627
520
|
return;
|
|
628
521
|
}
|
|
629
522
|
if (attempt < 40) {
|
|
@@ -634,8 +527,8 @@ function PayPalConnectionPage() {
|
|
|
634
527
|
document.dispatchEvent(new Event("DOMContentLoaded"));
|
|
635
528
|
} catch {
|
|
636
529
|
}
|
|
530
|
+
markReady();
|
|
637
531
|
};
|
|
638
|
-
partnerBoundRef.current = false;
|
|
639
532
|
const existingScript = document.getElementById("paypal-partner-js");
|
|
640
533
|
if (existingScript) {
|
|
641
534
|
(_a = existingScript.parentNode) == null ? void 0 : _a.removeChild(existingScript);
|
|
@@ -651,9 +544,11 @@ function PayPalConnectionPage() {
|
|
|
651
544
|
ppScript.src = scriptUrl;
|
|
652
545
|
ppScript.async = true;
|
|
653
546
|
ppScript.onload = () => initPartner();
|
|
547
|
+
ppScript.onerror = () => markReady();
|
|
654
548
|
document.body.appendChild(ppScript);
|
|
655
549
|
return () => {
|
|
656
550
|
cancelled = true;
|
|
551
|
+
clearTimeout(readyFallback);
|
|
657
552
|
if (pollTimer) {
|
|
658
553
|
clearTimeout(pollTimer);
|
|
659
554
|
}
|
|
@@ -662,59 +557,61 @@ function PayPalConnectionPage() {
|
|
|
662
557
|
}
|
|
663
558
|
};
|
|
664
559
|
}, [connState, finalUrl, env]);
|
|
665
|
-
react.
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
560
|
+
const completeOnboarding = react.useCallback(async (authCode, sharedId) => {
|
|
561
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
562
|
+
if (!authCode || !sharedId) return;
|
|
563
|
+
if (completedRef.current) return;
|
|
564
|
+
completedRef.current = true;
|
|
565
|
+
try {
|
|
566
|
+
window.onbeforeunload = null;
|
|
567
|
+
} catch {
|
|
568
|
+
}
|
|
569
|
+
const activeEnv = envRef.current === "sandbox" ? "sandbox" : "live";
|
|
570
|
+
setOnboardingInProgress(true);
|
|
571
|
+
setConnState("loading");
|
|
572
|
+
setError(null);
|
|
573
|
+
try {
|
|
574
|
+
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
575
|
+
method: "POST",
|
|
576
|
+
headers: { "content-type": "application/json" },
|
|
577
|
+
credentials: "include",
|
|
578
|
+
body: JSON.stringify({ authCode, sharedId, env: activeEnv })
|
|
579
|
+
});
|
|
580
|
+
if (!res.ok) {
|
|
581
|
+
const txt = await res.text().catch(() => "");
|
|
582
|
+
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
671
583
|
}
|
|
672
|
-
};
|
|
673
|
-
window.addEventListener("message", onMessage);
|
|
674
|
-
return () => window.removeEventListener("message", onMessage);
|
|
675
|
-
}, [completeOnboarding]);
|
|
676
|
-
react.useEffect(() => {
|
|
677
|
-
if (!envReady) return;
|
|
678
|
-
currentRunId.current = ++runIdRef.current;
|
|
679
|
-
const runId = currentRunId.current;
|
|
680
|
-
let cancelled = false;
|
|
681
|
-
completedRef.current = false;
|
|
682
|
-
const run = async () => {
|
|
683
|
-
setConnState("loading");
|
|
684
|
-
setError(null);
|
|
685
|
-
setPopupBlocked(false);
|
|
686
|
-
setFinalUrl("");
|
|
687
584
|
try {
|
|
688
|
-
const
|
|
585
|
+
const close1 = (_d = (_c = (_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) == null ? void 0 : _c.MiniBrowser) == null ? void 0 : _d.closeFlow;
|
|
586
|
+
if (typeof close1 === "function") close1();
|
|
587
|
+
} catch {
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
const close2 = ((_g = (_f = (_e = window.PAYPAL) == null ? void 0 : _e.apps) == null ? void 0 : _f.Signup) == null ? void 0 : _g.miniBrowser) && window.PAYPAL.apps.Signup.miniBrowser.closeFlow;
|
|
591
|
+
if (typeof close2 === "function") close2();
|
|
592
|
+
} catch {
|
|
593
|
+
}
|
|
594
|
+
clearCachedUrl(activeEnv);
|
|
595
|
+
try {
|
|
596
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${activeEnv}`, {
|
|
689
597
|
method: "GET",
|
|
690
598
|
credentials: "include"
|
|
691
599
|
});
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
const isConnected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
|
|
696
|
-
if (isConnected) {
|
|
697
|
-
setConnState("connected");
|
|
698
|
-
setShowManual(false);
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
|
-
} catch (e) {
|
|
702
|
-
console.error(e);
|
|
703
|
-
}
|
|
704
|
-
if (cancelled || runId !== currentRunId.current) return;
|
|
705
|
-
const cached = readCachedUrl(env);
|
|
706
|
-
if (cached) {
|
|
707
|
-
setFinalUrl(cached);
|
|
708
|
-
setConnState("ready");
|
|
709
|
-
} else {
|
|
710
|
-
fetchFreshLink(runId, env);
|
|
600
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
601
|
+
setStatusInfo(refreshedStatus || null);
|
|
602
|
+
} catch {
|
|
711
603
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
604
|
+
setConnState("connected");
|
|
605
|
+
setShowManual(false);
|
|
606
|
+
} catch (e) {
|
|
607
|
+
completedRef.current = false;
|
|
608
|
+
console.error(e);
|
|
609
|
+
setConnState("error");
|
|
610
|
+
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
611
|
+
} finally {
|
|
612
|
+
setOnboardingInProgress(false);
|
|
613
|
+
}
|
|
614
|
+
}, []);
|
|
718
615
|
react.useLayoutEffect(() => {
|
|
719
616
|
window.onboardingCallback = (authCode, sharedId) => {
|
|
720
617
|
completeOnboarding(authCode, sharedId);
|
|
@@ -723,11 +620,6 @@ function PayPalConnectionPage() {
|
|
|
723
620
|
window.onboardingCallback = void 0;
|
|
724
621
|
};
|
|
725
622
|
}, [completeOnboarding]);
|
|
726
|
-
react.useEffect(() => {
|
|
727
|
-
return () => {
|
|
728
|
-
stopPopupPoll();
|
|
729
|
-
};
|
|
730
|
-
}, [stopPopupPoll]);
|
|
731
623
|
react.useLayoutEffect(() => {
|
|
732
624
|
const el = ppBtnMeasureRef.current;
|
|
733
625
|
if (!el) return;
|
|
@@ -748,18 +640,6 @@ function PayPalConnectionPage() {
|
|
|
748
640
|
else window.removeEventListener("resize", update);
|
|
749
641
|
};
|
|
750
642
|
}, [connState, env, finalUrl]);
|
|
751
|
-
const handleConnectClick = (e) => {
|
|
752
|
-
e.preventDefault();
|
|
753
|
-
if (connStateRef.current !== "ready" || !finalUrlRef.current || inProgressRef.current) {
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
if (partnerBoundRef.current) {
|
|
757
|
-
return;
|
|
758
|
-
}
|
|
759
|
-
completedRef.current = false;
|
|
760
|
-
const popup = openOnboardingPopup(finalUrlRef.current);
|
|
761
|
-
setPopupBlocked(!popup);
|
|
762
|
-
};
|
|
763
643
|
const handleSaveManual = async () => {
|
|
764
644
|
if (!canSaveManual || onboardingInProgress) return;
|
|
765
645
|
setOnboardingInProgress(true);
|
|
@@ -820,8 +700,7 @@ function PayPalConnectionPage() {
|
|
|
820
700
|
clearCachedUrl(env);
|
|
821
701
|
completedRef.current = false;
|
|
822
702
|
currentRunId.current = ++runIdRef.current;
|
|
823
|
-
|
|
824
|
-
fetchFreshLink(runId, env);
|
|
703
|
+
await generateLinkAndReload(env, currentRunId.current);
|
|
825
704
|
} catch (e) {
|
|
826
705
|
console.error(e);
|
|
827
706
|
setConnState("error");
|
|
@@ -832,10 +711,10 @@ function PayPalConnectionPage() {
|
|
|
832
711
|
};
|
|
833
712
|
const handleEnvChange = async (e) => {
|
|
834
713
|
const next = e.target.value;
|
|
714
|
+
if (next === env || onboardingInProgress) return;
|
|
835
715
|
completedRef.current = false;
|
|
836
|
-
setPopupBlocked(false);
|
|
837
716
|
clearCachedUrl();
|
|
838
|
-
|
|
717
|
+
setConnState("loading");
|
|
839
718
|
try {
|
|
840
719
|
await fetch(ENVIRONMENT_ENDPOINT, {
|
|
841
720
|
method: "POST",
|
|
@@ -845,6 +724,7 @@ function PayPalConnectionPage() {
|
|
|
845
724
|
});
|
|
846
725
|
} catch {
|
|
847
726
|
}
|
|
727
|
+
setEnv(next);
|
|
848
728
|
};
|
|
849
729
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6", children: [
|
|
850
730
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
@@ -904,7 +784,6 @@ function PayPalConnectionPage() {
|
|
|
904
784
|
"a",
|
|
905
785
|
{
|
|
906
786
|
ref: (node) => {
|
|
907
|
-
paypalButtonRef.current = node;
|
|
908
787
|
ppBtnMeasureRef.current = node;
|
|
909
788
|
},
|
|
910
789
|
id: "paypal-button",
|
|
@@ -912,17 +791,19 @@ function PayPalConnectionPage() {
|
|
|
912
791
|
"data-paypal-button": "true",
|
|
913
792
|
href: finalUrl || "#",
|
|
914
793
|
"data-paypal-onboard-complete": "onboardingCallback",
|
|
915
|
-
|
|
794
|
+
"aria-disabled": onboardingInProgress || !partnerReady,
|
|
916
795
|
className: "transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none no-underline shadow-buttons-neutral text-ui-fg-base bg-ui-button-neutral after:transition-fg after:absolute after:inset-0 after:content-[''] after:button-neutral-gradient hover:bg-ui-button-neutral-hover hover:after:button-neutral-hover-gradient active:bg-ui-button-neutral-pressed active:after:button-neutral-pressed-gradient focus-visible:shadow-buttons-neutral-focus disabled:bg-ui-bg-disabled disabled:border-ui-border-base disabled:text-ui-fg-disabled disabled:shadow-buttons-neutral disabled:after:hidden txt-compact-small-plus px-3 py-1.5",
|
|
917
796
|
style: {
|
|
918
|
-
cursor: onboardingInProgress ? "not-allowed" : "pointer",
|
|
919
|
-
opacity: onboardingInProgress ? 0.6 : 1,
|
|
920
|
-
|
|
797
|
+
cursor: onboardingInProgress || !partnerReady ? "not-allowed" : "pointer",
|
|
798
|
+
opacity: onboardingInProgress || !partnerReady ? 0.6 : 1,
|
|
799
|
+
// Keep the anchor mounted (partner.js must find it to bind)
|
|
800
|
+
// but un-clickable until partner.js has taken over the
|
|
801
|
+
// click — so it can never open a tab via the native href.
|
|
802
|
+
pointerEvents: onboardingInProgress || !partnerReady ? "none" : "auto"
|
|
921
803
|
},
|
|
922
|
-
children: "Connect to PayPal"
|
|
804
|
+
children: partnerReady || onboardingInProgress ? "Connect to PayPal" : "Preparing PayPal…"
|
|
923
805
|
}
|
|
924
806
|
),
|
|
925
|
-
popupBlocked && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 text-left text-xs bg-amber-50 text-amber-700 p-3 border border-amber-200 rounded", children: "Your browser blocked the PayPal popup. Please allow popups for this site, then click “Connect to PayPal” again." }),
|
|
926
807
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
927
808
|
"div",
|
|
928
809
|
{
|
|
@@ -1078,9 +959,6 @@ function PayPalConnectionPage() {
|
|
|
1078
959
|
` })
|
|
1079
960
|
] });
|
|
1080
961
|
}
|
|
1081
|
-
function PayPalGooglePayPage() {
|
|
1082
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1083
|
-
}
|
|
1084
962
|
function PayPalPayLaterMessagingPage() {
|
|
1085
963
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1086
964
|
}
|
|
@@ -1302,22 +1180,22 @@ const routeModule = {
|
|
|
1302
1180
|
Component: AdditionalSettingsTab,
|
|
1303
1181
|
path: "/settings/paypal/additional-settings"
|
|
1304
1182
|
},
|
|
1305
|
-
{
|
|
1306
|
-
Component: PayPalApplePayPage,
|
|
1307
|
-
path: "/settings/paypal/apple-pay"
|
|
1308
|
-
},
|
|
1309
1183
|
{
|
|
1310
1184
|
Component: AdvancedCardPaymentsTab,
|
|
1311
1185
|
path: "/settings/paypal/advanced-card-payments"
|
|
1312
1186
|
},
|
|
1313
1187
|
{
|
|
1314
|
-
Component:
|
|
1315
|
-
path: "/settings/paypal/
|
|
1188
|
+
Component: PayPalApplePayPage,
|
|
1189
|
+
path: "/settings/paypal/apple-pay"
|
|
1316
1190
|
},
|
|
1317
1191
|
{
|
|
1318
1192
|
Component: PayPalGooglePayPage,
|
|
1319
1193
|
path: "/settings/paypal/google-pay"
|
|
1320
1194
|
},
|
|
1195
|
+
{
|
|
1196
|
+
Component: PayPalConnectionPage,
|
|
1197
|
+
path: "/settings/paypal/connection"
|
|
1198
|
+
},
|
|
1321
1199
|
{
|
|
1322
1200
|
Component: PayPalPayLaterMessagingPage,
|
|
1323
1201
|
path: "/settings/paypal/pay-later-messaging"
|