@easypayment/medusa-payment-paypal 0.9.25 → 0.9.26

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.
@@ -307,21 +307,17 @@ function AdvancedCardPaymentsTab() {
307
307
  )
308
308
  ] }) });
309
309
  }
310
- function PayPalApplePayPage() {
310
+ function PayPalGooglePayPage() {
311
311
  return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
312
312
  }
313
- function PayPalGooglePayPage() {
313
+ function PayPalApplePayPage() {
314
314
  return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
315
315
  }
316
316
  const config = defineRouteConfig({
317
317
  label: "PayPal Connection"
318
318
  });
319
- const PARTNER_JS_URLS = {
320
- sandbox: "https://www.sandbox.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js",
321
- live: "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js"
322
- };
319
+ const PARTNER_JS_URL = "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js";
323
320
  const SERVICE_URL = "/admin/paypal/onboarding-link";
324
- const POPUP_NAME = "PPFrame";
325
321
  const CACHE_PREFIX = "pp_onboard_cache";
326
322
  const CACHE_EXPIRY = 6 * 60 * 60 * 1e3;
327
323
  const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
@@ -346,9 +342,7 @@ function readCachedUrl(env) {
346
342
  function writeCachedUrl(env, url) {
347
343
  try {
348
344
  localStorage.setItem(cacheKeyFor(env), JSON.stringify({ url, ts: Date.now() }));
349
- return readCachedUrl(env) === url;
350
345
  } catch {
351
- return false;
352
346
  }
353
347
  }
354
348
  function clearCachedUrl(env) {
@@ -362,62 +356,11 @@ function clearCachedUrl(env) {
362
356
  } catch {
363
357
  }
364
358
  }
365
- function isPayPalOrigin(origin) {
366
- try {
367
- const host = new URL(origin).hostname.toLowerCase();
368
- return host === "www.paypal.com" || host === "www.sandbox.paypal.com" || host.endsWith(".paypal.com") || host.endsWith(".paypalobjects.com");
369
- } catch {
370
- return false;
371
- }
372
- }
373
- function extractAuth(data) {
374
- if (!data) return {};
375
- if (typeof data === "object") {
376
- const obj = data;
377
- const authCode = obj.authCode ?? obj.auth_code ?? obj.authcode ?? obj.code;
378
- const sharedId = obj.sharedId ?? obj.shared_id ?? obj.sharedid;
379
- if (authCode && sharedId) {
380
- return { authCode: String(authCode), sharedId: String(sharedId) };
381
- }
382
- for (const key of ["data", "payload", "message", "detail", "body", "params"]) {
383
- if (obj[key] && typeof obj[key] === "object") {
384
- const inner = extractAuth(obj[key]);
385
- if (inner.authCode && inner.sharedId) return inner;
386
- }
387
- if (typeof obj[key] === "string") {
388
- const inner = extractAuth(obj[key]);
389
- if (inner.authCode && inner.sharedId) return inner;
390
- }
391
- }
392
- return {};
393
- }
394
- if (typeof data === "string") {
395
- const s = data.trim();
396
- if (!s) return {};
397
- if (s.startsWith("{") || s.startsWith("[")) {
398
- try {
399
- return extractAuth(JSON.parse(s));
400
- } catch {
401
- }
402
- }
403
- if (/auth_?code/i.test(s) && /shared_?id/i.test(s)) {
404
- try {
405
- const sp = new URLSearchParams(s.replace(/^[?#]/, ""));
406
- const authCode = sp.get("authCode") || sp.get("auth_code") || void 0;
407
- const sharedId = sp.get("sharedId") || sp.get("shared_id") || void 0;
408
- if (authCode && sharedId) return { authCode, sharedId };
409
- } catch {
410
- }
411
- }
412
- }
413
- return {};
414
- }
415
359
  function PayPalConnectionPage() {
416
360
  const [env, setEnv] = useState("live");
417
361
  const [envReady, setEnvReady] = useState(false);
418
362
  const [connState, setConnState] = useState("loading");
419
363
  const [error, setError] = useState(null);
420
- const [popupBlocked, setPopupBlocked] = useState(false);
421
364
  const [finalUrl, setFinalUrl] = useState("");
422
365
  const [showManual, setShowManual] = useState(false);
423
366
  const [clientId, setClientId] = useState("");
@@ -429,17 +372,11 @@ function PayPalConnectionPage() {
429
372
  const errorLogRef = useRef(null);
430
373
  const runIdRef = useRef(0);
431
374
  const currentRunId = useRef(0);
375
+ const completedRef = useRef(false);
432
376
  const envRef = useRef(env);
433
377
  envRef.current = env;
434
- const finalUrlRef = useRef(finalUrl);
435
- finalUrlRef.current = finalUrl;
436
- const connStateRef = useRef(connState);
437
- connStateRef.current = connState;
438
- const inProgressRef = useRef(onboardingInProgress);
439
- inProgressRef.current = onboardingInProgress;
440
- const popupRef = useRef(null);
441
- const pollRef = useRef(null);
442
- const completedRef = useRef(false);
378
+ const pollTimerRef = useRef(null);
379
+ const pollAttemptsRef = useRef(0);
443
380
  const ppBtnMeasureRef = useRef(null);
444
381
  const [ppBtnWidth, setPpBtnWidth] = useState(null);
445
382
  const canSaveManual = useMemo(() => {
@@ -449,44 +386,72 @@ function PayPalConnectionPage() {
449
386
  setConnState("error");
450
387
  setError(msg);
451
388
  }, []);
452
- const stopPoll = useCallback(() => {
453
- if (pollRef.current) {
454
- clearInterval(pollRef.current);
455
- pollRef.current = null;
389
+ const closeMiniBrowser = useCallback(() => {
390
+ var _a, _b, _c, _d, _e, _f, _g, _h;
391
+ try {
392
+ 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;
393
+ if (typeof close1 === "function") close1();
394
+ } catch {
456
395
  }
457
- }, []);
458
- const openOnboardingPopup = useCallback((url) => {
459
- const w = 450;
460
- const h = 600;
461
- const baseLeft = typeof window.screenX === "number" ? window.screenX : window.screenLeft || 0;
462
- const baseTop = typeof window.screenY === "number" ? window.screenY : window.screenTop || 0;
463
- const outerW = window.outerWidth || document.documentElement.clientWidth || 1024;
464
- const outerH = window.outerHeight || document.documentElement.clientHeight || 768;
465
- const left = Math.round(baseLeft + Math.max(0, (outerW - w) / 2));
466
- const top = Math.round(baseTop + Math.max(0, (outerH - h) / 2));
467
- const features = `popup=yes,width=${w},height=${h},left=${left},top=${top},scrollbars=yes,resizable=yes`;
468
- let popup = null;
469
396
  try {
470
- popup = window.open(url, POPUP_NAME, features);
397
+ const close2 = (_h = (_g = (_f = (_e = window.PAYPAL) == null ? void 0 : _e.apps) == null ? void 0 : _f.Signup) == null ? void 0 : _g.miniBrowser) == null ? void 0 : _h.closeFlow;
398
+ if (typeof close2 === "function") close2();
471
399
  } catch {
472
- popup = null;
473
400
  }
474
- if (popup) {
475
- popupRef.current = popup;
401
+ }, []);
402
+ const stopStatusPolling = useCallback(() => {
403
+ if (pollTimerRef.current) {
404
+ clearTimeout(pollTimerRef.current);
405
+ pollTimerRef.current = null;
406
+ }
407
+ pollAttemptsRef.current = 0;
408
+ }, []);
409
+ const refreshStatusAndMaybeConnect = useCallback(
410
+ async (activeEnv) => {
476
411
  try {
477
- popup.focus();
412
+ const res = await fetch(`${STATUS_ENDPOINT}?environment=${activeEnv}`, {
413
+ method: "GET",
414
+ credentials: "include"
415
+ });
416
+ const st = await res.json().catch(() => ({}));
417
+ const connected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
418
+ if (connected) {
419
+ completedRef.current = true;
420
+ setStatusInfo(st);
421
+ setConnState("connected");
422
+ setShowManual(false);
423
+ setOnboardingInProgress(false);
424
+ clearCachedUrl(activeEnv);
425
+ closeMiniBrowser();
426
+ stopStatusPolling();
427
+ }
428
+ return connected;
478
429
  } catch {
430
+ return false;
479
431
  }
480
- }
481
- return popup;
482
- }, []);
432
+ },
433
+ [closeMiniBrowser, stopStatusPolling]
434
+ );
435
+ const startStatusPolling = useCallback(() => {
436
+ stopStatusPolling();
437
+ const MAX_ATTEMPTS = 100;
438
+ const tick = async () => {
439
+ pollAttemptsRef.current += 1;
440
+ const connected = await refreshStatusAndMaybeConnect(envRef.current);
441
+ if (connected || completedRef.current) return;
442
+ if (pollAttemptsRef.current >= MAX_ATTEMPTS) {
443
+ stopStatusPolling();
444
+ return;
445
+ }
446
+ pollTimerRef.current = setTimeout(tick, 3e3);
447
+ };
448
+ pollTimerRef.current = setTimeout(tick, 3e3);
449
+ }, [refreshStatusAndMaybeConnect, stopStatusPolling]);
483
450
  const completeOnboarding = useCallback(
484
451
  async (authCode, sharedId) => {
485
- var _a, _b, _c, _d, _e, _f, _g, _h;
486
452
  if (!authCode || !sharedId) return;
487
453
  if (completedRef.current) return;
488
454
  completedRef.current = true;
489
- stopPoll();
490
455
  try {
491
456
  window.onbeforeunload = null;
492
457
  } catch {
@@ -495,7 +460,6 @@ function PayPalConnectionPage() {
495
460
  setOnboardingInProgress(true);
496
461
  setConnState("loading");
497
462
  setError(null);
498
- setPopupBlocked(false);
499
463
  try {
500
464
  const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
501
465
  method: "POST",
@@ -507,32 +471,20 @@ function PayPalConnectionPage() {
507
471
  const txt = await res.text().catch(() => "");
508
472
  throw new Error(txt || `Onboarding exchange failed (${res.status})`);
509
473
  }
510
- try {
511
- (_a = popupRef.current) == null ? void 0 : _a.close();
512
- } catch {
513
- }
514
- try {
515
- 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;
516
- if (typeof close1 === "function") close1();
517
- } catch {
518
- }
519
- try {
520
- 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;
521
- if (typeof close2 === "function") close2();
522
- } catch {
523
- }
474
+ closeMiniBrowser();
524
475
  clearCachedUrl(activeEnv);
525
476
  try {
526
- const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${activeEnv}`, {
527
- method: "GET",
528
- credentials: "include"
529
- });
477
+ const statusRes = await fetch(
478
+ `${STATUS_ENDPOINT}?environment=${activeEnv}`,
479
+ { method: "GET", credentials: "include" }
480
+ );
530
481
  const refreshedStatus = await statusRes.json().catch(() => ({}));
531
482
  setStatusInfo(refreshedStatus || null);
532
483
  } catch {
533
484
  }
534
485
  setConnState("connected");
535
486
  setShowManual(false);
487
+ stopStatusPolling();
536
488
  } catch (e) {
537
489
  completedRef.current = false;
538
490
  console.error(e);
@@ -542,42 +494,72 @@ function PayPalConnectionPage() {
542
494
  setOnboardingInProgress(false);
543
495
  }
544
496
  },
545
- [stopPoll]
497
+ [closeMiniBrowser, stopStatusPolling]
546
498
  );
547
- const startStatusPoll = useCallback(() => {
548
- stopPoll();
549
- let ticks = 0;
550
- pollRef.current = setInterval(async () => {
551
- var _a;
552
- ticks += 1;
553
- if (completedRef.current || ticks > 150) {
554
- stopPoll();
555
- return;
556
- }
499
+ const initPartner = useCallback(() => {
500
+ var _a, _b;
501
+ const signup = (_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup;
502
+ const init = (signup == null ? void 0 : signup.miniBrowser) && signup.miniBrowser.init || (signup == null ? void 0 : signup.MiniBrowser) && signup.MiniBrowser.init;
503
+ if (typeof init === "function") {
557
504
  try {
558
- const r = await fetch(`${STATUS_ENDPOINT}?environment=${envRef.current}`, {
559
- method: "GET",
560
- credentials: "include"
561
- });
562
- const st = await r.json().catch(() => ({}));
563
- if ((st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true) {
564
- completedRef.current = true;
565
- stopPoll();
566
- try {
567
- (_a = popupRef.current) == null ? void 0 : _a.close();
568
- } catch {
569
- }
570
- clearCachedUrl(envRef.current);
571
- setStatusInfo(st);
572
- setConnState("connected");
573
- setShowManual(false);
574
- setOnboardingInProgress(false);
575
- }
576
- } catch {
505
+ init();
506
+ } catch (e) {
507
+ console.error("[paypal] partner.js init failed:", e);
577
508
  }
578
- }, 2e3);
579
- }, [stopPoll]);
580
- const generateLinkAndReload = useCallback(
509
+ }
510
+ }, []);
511
+ useEffect(() => {
512
+ const existingScript = document.getElementById("paypal-partner-js");
513
+ if (existingScript) return;
514
+ const preloadHref = PARTNER_JS_URL;
515
+ let preloadLink = null;
516
+ if (!document.head.querySelector(`link[rel="preload"][href="${preloadHref}"]`)) {
517
+ preloadLink = document.createElement("link");
518
+ preloadLink.rel = "preload";
519
+ preloadLink.href = preloadHref;
520
+ preloadLink.as = "script";
521
+ document.head.appendChild(preloadLink);
522
+ }
523
+ const ppScript = document.createElement("script");
524
+ ppScript.id = "paypal-partner-js";
525
+ ppScript.src = preloadHref;
526
+ ppScript.async = true;
527
+ document.head.appendChild(ppScript);
528
+ return () => {
529
+ if (preloadLink == null ? void 0 : preloadLink.parentNode) preloadLink.parentNode.removeChild(preloadLink);
530
+ if (ppScript.parentNode) ppScript.parentNode.removeChild(ppScript);
531
+ };
532
+ }, []);
533
+ const activatePayPal = useCallback(
534
+ (url, runId) => {
535
+ if (paypalButtonRef.current) {
536
+ paypalButtonRef.current.href = url;
537
+ }
538
+ setFinalUrl(url);
539
+ let attempts = 0;
540
+ const MAX_ATTEMPTS = 200;
541
+ const tryInit = () => {
542
+ var _a, _b;
543
+ if (runId !== currentRunId.current) return;
544
+ if ((_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) {
545
+ initPartner();
546
+ setConnState("ready");
547
+ return;
548
+ }
549
+ attempts++;
550
+ if (attempts >= MAX_ATTEMPTS) {
551
+ showError(
552
+ "PayPal partner script failed to load. Please refresh and try again."
553
+ );
554
+ return;
555
+ }
556
+ setTimeout(tryInit, 50);
557
+ };
558
+ tryInit();
559
+ },
560
+ [initPartner, showError]
561
+ );
562
+ const fetchFreshLink = useCallback(
581
563
  async (targetEnv, runId) => {
582
564
  if (initLoaderRef.current) {
583
565
  const loaderText = initLoaderRef.current.querySelector("#loader-text");
@@ -599,19 +581,14 @@ function PayPalConnectionPage() {
599
581
  return;
600
582
  }
601
583
  const url = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
602
- const persisted = writeCachedUrl(targetEnv, url);
603
- if (persisted) {
604
- window.location.reload();
605
- return;
606
- }
607
- setFinalUrl(url);
608
- setConnState("ready");
584
+ writeCachedUrl(targetEnv, url);
585
+ activatePayPal(url, runId);
609
586
  } catch {
610
587
  if (runId !== currentRunId.current) return;
611
588
  showError("Unable to connect to service.");
612
589
  }
613
590
  },
614
- [showError]
591
+ [activatePayPal, showError]
615
592
  );
616
593
  useEffect(() => {
617
594
  let alive = true;
@@ -635,7 +612,6 @@ function PayPalConnectionPage() {
635
612
  const run = async () => {
636
613
  setConnState("loading");
637
614
  setError(null);
638
- setPopupBlocked(false);
639
615
  setFinalUrl("");
640
616
  try {
641
617
  const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
@@ -657,149 +633,43 @@ function PayPalConnectionPage() {
657
633
  if (cancelled || runId !== currentRunId.current) return;
658
634
  const cached = readCachedUrl(env);
659
635
  if (cached) {
660
- setFinalUrl(cached);
661
- setConnState("ready");
636
+ activatePayPal(cached, runId);
662
637
  return;
663
638
  }
664
- await generateLinkAndReload(env, runId);
639
+ await fetchFreshLink(env, runId);
665
640
  };
666
641
  run();
667
642
  return () => {
668
643
  cancelled = true;
669
644
  };
670
- }, [env, envReady, generateLinkAndReload]);
671
- useEffect(() => {
672
- var _a, _b, _c;
673
- if (connState !== "ready" || !finalUrl) return;
674
- const scriptUrl = PARTNER_JS_URLS[env];
675
- let cancelled = false;
676
- let pollTimer;
677
- const initPartner = (attempt = 0) => {
678
- var _a2, _b2;
679
- if (cancelled) return;
680
- const signup = (_b2 = (_a2 = window.PAYPAL) == null ? void 0 : _a2.apps) == null ? void 0 : _b2.Signup;
681
- const target = (signup == null ? void 0 : signup.miniBrowser) && typeof signup.miniBrowser.init === "function" ? signup.miniBrowser : (signup == null ? void 0 : signup.MiniBrowser) && typeof signup.MiniBrowser.init === "function" ? signup.MiniBrowser : null;
682
- if (target == null ? void 0 : target.init) {
683
- try {
684
- target.init();
685
- } catch (e) {
686
- console.error("[paypal] partner.js init failed:", e);
687
- }
688
- return;
689
- }
690
- if (typeof (signup == null ? void 0 : signup.render) === "function") {
691
- try {
692
- signup.render();
693
- } catch (e) {
694
- console.error("[paypal] partner.js render failed:", e);
695
- }
696
- return;
697
- }
698
- if (attempt < 40) {
699
- pollTimer = setTimeout(() => initPartner(attempt + 1), 50);
700
- return;
701
- }
702
- try {
703
- document.dispatchEvent(new Event("DOMContentLoaded"));
704
- } catch {
705
- }
706
- };
707
- const existingScript = document.getElementById("paypal-partner-js");
708
- if (existingScript) {
709
- (_a = existingScript.parentNode) == null ? void 0 : _a.removeChild(existingScript);
710
- }
711
- if ((_c = (_b = window.PAYPAL) == null ? void 0 : _b.apps) == null ? void 0 : _c.Signup) {
712
- try {
713
- delete window.PAYPAL.apps.Signup;
714
- } catch {
715
- }
716
- }
717
- const ppScript = document.createElement("script");
718
- ppScript.id = "paypal-partner-js";
719
- ppScript.src = scriptUrl;
720
- ppScript.async = true;
721
- ppScript.onload = () => initPartner();
722
- document.body.appendChild(ppScript);
723
- return () => {
724
- cancelled = true;
725
- if (pollTimer) clearTimeout(pollTimer);
726
- if (ppScript.parentNode) ppScript.parentNode.removeChild(ppScript);
727
- };
728
- }, [connState, finalUrl, env]);
729
- useEffect(() => {
730
- const onMessage = (ev) => {
731
- var _a;
732
- let serialized = "";
733
- try {
734
- serialized = typeof ev.data === "string" ? ev.data : JSON.stringify(ev.data);
735
- } catch {
736
- serialized = String(ev.data);
737
- }
738
- const looksRelevant = isPayPalOrigin(ev.origin) || /auth_?code|shared_?id|onboard|merchantId/i.test(serialized || "");
739
- if (looksRelevant) {
740
- console.info(
741
- "[PayPal onboarding] message from",
742
- ev.origin,
743
- "·",
744
- (serialized || "").slice(0, 500)
745
- );
746
- }
747
- const d = ev.data;
748
- if (d && typeof d === "object" && d.source === "paypal-onboarding-return") {
749
- try {
750
- (_a = popupRef.current) == null ? void 0 : _a.close();
751
- } catch {
752
- }
753
- const fromReturn = extractAuth(d.params);
754
- if (fromReturn.authCode && fromReturn.sharedId) {
755
- completeOnboarding(fromReturn.authCode, fromReturn.sharedId);
756
- } else if (!completedRef.current) {
757
- startStatusPoll();
758
- }
759
- return;
760
- }
761
- if (!isPayPalOrigin(ev.origin)) return;
762
- const { authCode, sharedId } = extractAuth(ev.data);
763
- if (authCode && sharedId) {
764
- completeOnboarding(authCode, sharedId);
765
- }
766
- };
767
- window.addEventListener("message", onMessage);
768
- return () => window.removeEventListener("message", onMessage);
769
- }, [completeOnboarding, startStatusPoll]);
645
+ }, [env, envReady, fetchFreshLink, activatePayPal]);
770
646
  useLayoutEffect(() => {
771
647
  window.onboardingCallback = (authCode, sharedId) => {
772
- completeOnboarding(authCode, sharedId);
648
+ void completeOnboarding(authCode, sharedId);
773
649
  };
774
650
  return () => {
775
651
  window.onboardingCallback = void 0;
776
652
  };
777
653
  }, [completeOnboarding]);
778
654
  useEffect(() => {
779
- const onCaptureClick = (e) => {
780
- const btn = paypalButtonRef.current;
781
- if (!btn) return;
782
- const target = e.target;
783
- if (!target || !btn.contains(target)) return;
784
- e.preventDefault();
785
- if (connStateRef.current !== "ready" || !finalUrlRef.current || inProgressRef.current) {
786
- return;
787
- }
788
- completedRef.current = false;
789
- const popup = openOnboardingPopup(finalUrlRef.current);
790
- if (!popup) {
791
- setPopupBlocked(true);
792
- return;
793
- }
794
- setPopupBlocked(false);
795
- startStatusPoll();
655
+ const onMessage = (event) => {
656
+ const data = event == null ? void 0 : event.data;
657
+ if (!data || data.source !== "paypal-onboarding-return") return;
658
+ const params = data.params || {};
659
+ const authCode = params.authCode || params.auth_code;
660
+ const sharedId = params.sharedId || params.shared_id;
661
+ const activeEnv = envRef.current;
662
+ void (async () => {
663
+ const connected = await refreshStatusAndMaybeConnect(activeEnv);
664
+ if (!connected && authCode && sharedId) {
665
+ await completeOnboarding(authCode, sharedId);
666
+ }
667
+ })();
796
668
  };
797
- document.addEventListener("click", onCaptureClick, true);
798
- return () => document.removeEventListener("click", onCaptureClick, true);
799
- }, [openOnboardingPopup, startStatusPoll]);
800
- useEffect(() => {
801
- return () => stopPoll();
802
- }, [stopPoll]);
669
+ window.addEventListener("message", onMessage);
670
+ return () => window.removeEventListener("message", onMessage);
671
+ }, [completeOnboarding, refreshStatusAndMaybeConnect]);
672
+ useEffect(() => stopStatusPolling, [stopStatusPolling]);
803
673
  useLayoutEffect(() => {
804
674
  const el = ppBtnMeasureRef.current;
805
675
  if (!el) return;
@@ -821,7 +691,12 @@ function PayPalConnectionPage() {
821
691
  };
822
692
  }, [connState, env, finalUrl]);
823
693
  const handleConnectClick = (e) => {
824
- e.preventDefault();
694
+ if (connState !== "ready" || !finalUrl || onboardingInProgress) {
695
+ e.preventDefault();
696
+ return;
697
+ }
698
+ completedRef.current = false;
699
+ startStatusPolling();
825
700
  };
826
701
  const handleSaveManual = async () => {
827
702
  if (!canSaveManual || onboardingInProgress) return;
@@ -863,6 +738,7 @@ function PayPalConnectionPage() {
863
738
  const handleDisconnect = async () => {
864
739
  if (onboardingInProgress) return;
865
740
  if (!window.confirm("Disconnect PayPal for this environment?")) return;
741
+ stopStatusPolling();
866
742
  setOnboardingInProgress(true);
867
743
  setConnState("loading");
868
744
  setError(null);
@@ -883,7 +759,7 @@ function PayPalConnectionPage() {
883
759
  clearCachedUrl(env);
884
760
  completedRef.current = false;
885
761
  currentRunId.current = ++runIdRef.current;
886
- await generateLinkAndReload(env, currentRunId.current);
762
+ await fetchFreshLink(env, currentRunId.current);
887
763
  } catch (e) {
888
764
  console.error(e);
889
765
  setConnState("error");
@@ -895,9 +771,9 @@ function PayPalConnectionPage() {
895
771
  const handleEnvChange = async (e) => {
896
772
  const next = e.target.value;
897
773
  if (next === env || onboardingInProgress) return;
774
+ stopStatusPolling();
898
775
  completedRef.current = false;
899
776
  clearCachedUrl();
900
- setPopupBlocked(false);
901
777
  setConnState("loading");
902
778
  try {
903
779
  await fetch(ENVIRONMENT_ENDPOINT, {
@@ -931,7 +807,19 @@ function PayPalConnectionPage() {
931
807
  ) }),
932
808
  /* @__PURE__ */ jsx("div", { className: "text-sm font-medium pt-2", children: env === "sandbox" ? "Connect to PayPal (Sandbox)" : "Connect to PayPal" }),
933
809
  /* @__PURE__ */ jsx("div", { className: "max-w-xl", children: connState === "connected" ? /* @__PURE__ */ jsxs("div", { children: [
934
- /* @__PURE__ */ jsx("div", { className: "text-sm text-green-600 bg-green-50 p-3 rounded border border-green-200", children: "✅ Successfully connected to PayPal!" }),
810
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-green-600 bg-green-50 p-3 rounded border border-green-200", children: [
811
+ "✅ Successfully connected to PayPal!",
812
+ /* @__PURE__ */ jsx(
813
+ "a",
814
+ {
815
+ "data-paypal-button": "true",
816
+ "data-paypal-onboard-complete": "onboardingCallback",
817
+ href: "#",
818
+ style: { display: "none" },
819
+ children: "PayPal"
820
+ }
821
+ )
822
+ ] }),
935
823
  /* @__PURE__ */ jsxs("div", { className: "mt-3 rounded-md border border-ui-border-base bg-ui-bg-subtle p-3 text-xs text-ui-fg-subtle", children: [
936
824
  /* @__PURE__ */ jsx("div", { className: "font-medium text-ui-fg-base", children: "Connected PayPal account" }),
937
825
  /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
@@ -972,7 +860,6 @@ function PayPalConnectionPage() {
972
860
  ppBtnMeasureRef.current = node;
973
861
  },
974
862
  id: "paypal-button",
975
- target: POPUP_NAME,
976
863
  "data-paypal-button": "true",
977
864
  href: finalUrl || "#",
978
865
  "data-paypal-onboard-complete": "onboardingCallback",
@@ -986,7 +873,6 @@ function PayPalConnectionPage() {
986
873
  children: "Connect to PayPal"
987
874
  }
988
875
  ),
989
- popupBlocked && /* @__PURE__ */ 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." }),
990
876
  /* @__PURE__ */ jsx(
991
877
  "div",
992
878
  {
@@ -1367,14 +1253,14 @@ const routeModule = {
1367
1253
  Component: AdvancedCardPaymentsTab,
1368
1254
  path: "/settings/paypal/advanced-card-payments"
1369
1255
  },
1370
- {
1371
- Component: PayPalApplePayPage,
1372
- path: "/settings/paypal/apple-pay"
1373
- },
1374
1256
  {
1375
1257
  Component: PayPalGooglePayPage,
1376
1258
  path: "/settings/paypal/google-pay"
1377
1259
  },
1260
+ {
1261
+ Component: PayPalApplePayPage,
1262
+ path: "/settings/paypal/apple-pay"
1263
+ },
1378
1264
  {
1379
1265
  Component: PayPalConnectionPage,
1380
1266
  path: "/settings/paypal/connection"
@@ -12,7 +12,6 @@ declare global {
12
12
  init?: () => void;
13
13
  closeFlow?: () => void;
14
14
  };
15
- render?: () => void;
16
15
  };
17
16
  };
18
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../../../src/admin/routes/settings/paypal/connection/page.tsx"],"names":[],"mappings":"AAWA,eAAO,MAAM,MAAM,2CAEjB,CAAA;AAQF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,MAAM,CAAC,EAAE;YACP,IAAI,CAAC,EAAE;gBACL,MAAM,CAAC,EAAE;oBACP,WAAW,CAAC,EAAE;wBAAE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;wBAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;qBAAE,CAAA;oBAC3D,WAAW,CAAC,EAAE;wBAAE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;wBAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;qBAAE,CAAA;oBAC3D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;iBACpB,CAAA;aACF,CAAA;SACF,CAAA;QACD,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;KAClE;CACF;AAkID,MAAM,CAAC,OAAO,UAAU,oBAAoB,4CAo4B3C"}
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../../../src/admin/routes/settings/paypal/connection/page.tsx"],"names":[],"mappings":"AAWA,eAAO,MAAM,MAAM,2CAEjB,CAAA;AAaF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,MAAM,CAAC,EAAE;YACP,IAAI,CAAC,EAAE;gBACL,MAAM,CAAC,EAAE;oBACP,WAAW,CAAC,EAAE;wBAAE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;wBAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;qBAAE,CAAA;oBAC3D,WAAW,CAAC,EAAE;wBAAE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;wBAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;qBAAE,CAAA;iBAC5D,CAAA;aACF,CAAA;SACF,CAAA;QACD,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;KAClE;CACF;AAwDD,MAAM,CAAC,OAAO,UAAU,oBAAoB,4CA2yB3C"}