@easypayment/medusa-payment-paypal 0.9.18 → 0.9.19
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 +287 -118
- package/.medusa/server/src/admin/index.mjs +287 -118
- 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 +386 -127
- package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js.map +1 -1
- package/.medusa/server/src/api/admin/paypal/onboarding-link/route.d.ts.map +1 -1
- package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js +4 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js.map +1 -1
- package/.medusa/server/src/modules/paypal/service.d.ts +1 -0
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +5 -1
- package/.medusa/server/src/modules/paypal/service.js.map +1 -1
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/connection/page.tsx +419 -131
- package/src/api/admin/paypal/onboarding-link/route.ts +6 -0
- package/src/modules/paypal/service.ts +7 -2
|
@@ -307,6 +307,12 @@ function AdvancedCardPaymentsTab() {
|
|
|
307
307
|
)
|
|
308
308
|
] }) });
|
|
309
309
|
}
|
|
310
|
+
function PayPalApplePayPage() {
|
|
311
|
+
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
312
|
+
}
|
|
313
|
+
function PayPalGooglePayPage() {
|
|
314
|
+
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
315
|
+
}
|
|
310
316
|
const config = defineRouteConfig({
|
|
311
317
|
label: "PayPal Connection"
|
|
312
318
|
});
|
|
@@ -315,37 +321,97 @@ const PARTNER_JS_URLS = {
|
|
|
315
321
|
live: "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js"
|
|
316
322
|
};
|
|
317
323
|
const SERVICE_URL = "/admin/paypal/onboarding-link";
|
|
318
|
-
const
|
|
324
|
+
const POPUP_NAME = "PPMiniBrowser";
|
|
325
|
+
const CACHE_PREFIX = "pp_onboard_cache";
|
|
319
326
|
const CACHE_EXPIRY = 10 * 60 * 1e3;
|
|
320
327
|
const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
|
|
321
328
|
const STATUS_ENDPOINT = "/admin/paypal/status";
|
|
322
329
|
const SAVE_CREDENTIALS_ENDPOINT = "/admin/paypal/save-credentials";
|
|
323
330
|
const DISCONNECT_ENDPOINT = "/admin/paypal/disconnect";
|
|
324
|
-
|
|
325
|
-
|
|
331
|
+
const ENVIRONMENT_ENDPOINT = "/admin/paypal/environment";
|
|
332
|
+
const cacheKeyFor = (env) => `${CACHE_PREFIX}_${env}`;
|
|
333
|
+
function readCachedUrl(env) {
|
|
334
|
+
if (typeof window === "undefined") return null;
|
|
326
335
|
try {
|
|
327
|
-
const
|
|
328
|
-
if (
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
336
|
+
const raw = localStorage.getItem(cacheKeyFor(env));
|
|
337
|
+
if (!raw) return null;
|
|
338
|
+
const data = JSON.parse(raw);
|
|
339
|
+
if (data && typeof data.url === "string" && Date.now() - (Number(data.ts) || 0) < CACHE_EXPIRY) {
|
|
340
|
+
return data.url;
|
|
341
|
+
}
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
function writeCachedUrl(env, url) {
|
|
347
|
+
try {
|
|
348
|
+
localStorage.setItem(cacheKeyFor(env), JSON.stringify({ url, ts: Date.now() }));
|
|
349
|
+
} catch {
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function clearCachedUrl(env) {
|
|
353
|
+
try {
|
|
354
|
+
if (env) {
|
|
355
|
+
localStorage.removeItem(cacheKeyFor(env));
|
|
356
|
+
} else {
|
|
357
|
+
localStorage.removeItem(cacheKeyFor("sandbox"));
|
|
358
|
+
localStorage.removeItem(cacheKeyFor("live"));
|
|
359
|
+
}
|
|
360
|
+
} catch {
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function isPayPalOrigin(origin) {
|
|
364
|
+
try {
|
|
365
|
+
const host = new URL(origin).hostname.toLowerCase();
|
|
366
|
+
return host === "www.paypal.com" || host === "www.sandbox.paypal.com" || host.endsWith(".paypal.com") || host.endsWith(".paypalobjects.com");
|
|
367
|
+
} catch {
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function extractAuth(data) {
|
|
372
|
+
if (!data) return {};
|
|
373
|
+
if (typeof data === "object") {
|
|
374
|
+
const obj = data;
|
|
375
|
+
const authCode = obj.authCode ?? obj.auth_code ?? obj.authcode;
|
|
376
|
+
const sharedId = obj.sharedId ?? obj.shared_id ?? obj.sharedid;
|
|
377
|
+
if (authCode && sharedId) {
|
|
378
|
+
return { authCode: String(authCode), sharedId: String(sharedId) };
|
|
379
|
+
}
|
|
380
|
+
for (const key of ["data", "payload", "message", "detail", "body"]) {
|
|
381
|
+
if (obj[key] && typeof obj[key] === "object") {
|
|
382
|
+
const inner = extractAuth(obj[key]);
|
|
383
|
+
if (inner.authCode && inner.sharedId) return inner;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return {};
|
|
387
|
+
}
|
|
388
|
+
if (typeof data === "string") {
|
|
389
|
+
const s = data.trim();
|
|
390
|
+
if (!s) return {};
|
|
391
|
+
if (s.startsWith("{")) {
|
|
392
|
+
try {
|
|
393
|
+
return extractAuth(JSON.parse(s));
|
|
394
|
+
} catch {
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (/auth_?code/i.test(s) && /shared_?id/i.test(s)) {
|
|
398
|
+
try {
|
|
399
|
+
const sp = new URLSearchParams(s.replace(/^[?#]/, ""));
|
|
400
|
+
const authCode = sp.get("authCode") || sp.get("auth_code") || void 0;
|
|
401
|
+
const sharedId = sp.get("sharedId") || sp.get("shared_id") || void 0;
|
|
402
|
+
if (authCode && sharedId) return { authCode, sharedId };
|
|
403
|
+
} catch {
|
|
332
404
|
}
|
|
333
405
|
}
|
|
334
|
-
} catch (e) {
|
|
335
|
-
console.error("Cache read error:", e);
|
|
336
406
|
}
|
|
407
|
+
return {};
|
|
337
408
|
}
|
|
338
409
|
function PayPalConnectionPage() {
|
|
339
410
|
const [env, setEnv] = useState("live");
|
|
340
|
-
|
|
341
|
-
fetch("/admin/paypal/environment", { method: "GET", credentials: "include" }).then((r) => r.json()).then((d) => {
|
|
342
|
-
const v = (d == null ? void 0 : d.environment) === "sandbox" ? "sandbox" : "live";
|
|
343
|
-
setEnv(v);
|
|
344
|
-
}).catch(() => {
|
|
345
|
-
});
|
|
346
|
-
}, []);
|
|
411
|
+
const [envReady, setEnvReady] = useState(false);
|
|
347
412
|
const [connState, setConnState] = useState("loading");
|
|
348
413
|
const [error, setError] = useState(null);
|
|
414
|
+
const [popupBlocked, setPopupBlocked] = useState(false);
|
|
349
415
|
const [finalUrl, setFinalUrl] = useState("");
|
|
350
416
|
const [showManual, setShowManual] = useState(false);
|
|
351
417
|
const [clientId, setClientId] = useState("");
|
|
@@ -357,6 +423,17 @@ function PayPalConnectionPage() {
|
|
|
357
423
|
const errorLogRef = useRef(null);
|
|
358
424
|
const runIdRef = useRef(0);
|
|
359
425
|
const currentRunId = useRef(0);
|
|
426
|
+
const finalUrlRef = useRef(finalUrl);
|
|
427
|
+
finalUrlRef.current = finalUrl;
|
|
428
|
+
const connStateRef = useRef(connState);
|
|
429
|
+
connStateRef.current = connState;
|
|
430
|
+
const inProgressRef = useRef(onboardingInProgress);
|
|
431
|
+
inProgressRef.current = onboardingInProgress;
|
|
432
|
+
const envRef = useRef(env);
|
|
433
|
+
envRef.current = env;
|
|
434
|
+
const popupRef = useRef(null);
|
|
435
|
+
const popupPollRef = useRef(null);
|
|
436
|
+
const completedRef = useRef(false);
|
|
360
437
|
const ppBtnMeasureRef = useRef(null);
|
|
361
438
|
const [ppBtnWidth, setPpBtnWidth] = useState(null);
|
|
362
439
|
const canSaveManual = useMemo(() => {
|
|
@@ -366,8 +443,124 @@ function PayPalConnectionPage() {
|
|
|
366
443
|
setConnState("error");
|
|
367
444
|
setError(msg);
|
|
368
445
|
}, []);
|
|
446
|
+
const stopPopupPoll = useCallback(() => {
|
|
447
|
+
if (popupPollRef.current) {
|
|
448
|
+
clearInterval(popupPollRef.current);
|
|
449
|
+
popupPollRef.current = null;
|
|
450
|
+
}
|
|
451
|
+
}, []);
|
|
452
|
+
const openOnboardingPopup = useCallback(
|
|
453
|
+
(url) => {
|
|
454
|
+
const w = 450;
|
|
455
|
+
const h = 600;
|
|
456
|
+
const baseLeft = typeof window.screenX === "number" ? window.screenX : window.screenLeft || 0;
|
|
457
|
+
const baseTop = typeof window.screenY === "number" ? window.screenY : window.screenTop || 0;
|
|
458
|
+
const outerW = window.outerWidth || document.documentElement.clientWidth || 1024;
|
|
459
|
+
const outerH = window.outerHeight || document.documentElement.clientHeight || 768;
|
|
460
|
+
const left = Math.round(baseLeft + Math.max(0, (outerW - w) / 2));
|
|
461
|
+
const top = Math.round(baseTop + Math.max(0, (outerH - h) / 2));
|
|
462
|
+
const features = `popup=yes,width=${w},height=${h},left=${left},top=${top},scrollbars=yes,resizable=yes`;
|
|
463
|
+
let popup = null;
|
|
464
|
+
try {
|
|
465
|
+
popup = window.open(url, POPUP_NAME, features);
|
|
466
|
+
} catch {
|
|
467
|
+
popup = null;
|
|
468
|
+
}
|
|
469
|
+
if (popup) {
|
|
470
|
+
popupRef.current = popup;
|
|
471
|
+
try {
|
|
472
|
+
popup.focus();
|
|
473
|
+
} catch {
|
|
474
|
+
}
|
|
475
|
+
stopPopupPoll();
|
|
476
|
+
popupPollRef.current = setInterval(() => {
|
|
477
|
+
if (!popupRef.current || popupRef.current.closed) {
|
|
478
|
+
stopPopupPoll();
|
|
479
|
+
}
|
|
480
|
+
}, 1e3);
|
|
481
|
+
}
|
|
482
|
+
return popup;
|
|
483
|
+
},
|
|
484
|
+
[stopPopupPoll]
|
|
485
|
+
);
|
|
486
|
+
const openConnect = useCallback(() => {
|
|
487
|
+
if (connStateRef.current !== "ready" || !finalUrlRef.current || inProgressRef.current) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
completedRef.current = false;
|
|
491
|
+
const popup = openOnboardingPopup(finalUrlRef.current);
|
|
492
|
+
if (!popup) {
|
|
493
|
+
setPopupBlocked(true);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
setPopupBlocked(false);
|
|
497
|
+
}, [openOnboardingPopup]);
|
|
498
|
+
const completeOnboarding = useCallback(
|
|
499
|
+
async (authCode, sharedId) => {
|
|
500
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
501
|
+
if (!authCode || !sharedId) return;
|
|
502
|
+
if (completedRef.current) return;
|
|
503
|
+
completedRef.current = true;
|
|
504
|
+
try {
|
|
505
|
+
window.onbeforeunload = null;
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
const activeEnv = envRef.current === "sandbox" ? "sandbox" : "live";
|
|
509
|
+
setOnboardingInProgress(true);
|
|
510
|
+
setConnState("loading");
|
|
511
|
+
setError(null);
|
|
512
|
+
setPopupBlocked(false);
|
|
513
|
+
try {
|
|
514
|
+
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
515
|
+
method: "POST",
|
|
516
|
+
headers: { "content-type": "application/json" },
|
|
517
|
+
credentials: "include",
|
|
518
|
+
body: JSON.stringify({ authCode, sharedId, env: activeEnv })
|
|
519
|
+
});
|
|
520
|
+
if (!res.ok) {
|
|
521
|
+
const txt = await res.text().catch(() => "");
|
|
522
|
+
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
523
|
+
}
|
|
524
|
+
try {
|
|
525
|
+
(_a = popupRef.current) == null ? void 0 : _a.close();
|
|
526
|
+
} catch {
|
|
527
|
+
}
|
|
528
|
+
stopPopupPoll();
|
|
529
|
+
try {
|
|
530
|
+
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;
|
|
531
|
+
if (typeof close1 === "function") close1();
|
|
532
|
+
} catch {
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
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;
|
|
536
|
+
if (typeof close2 === "function") close2();
|
|
537
|
+
} catch {
|
|
538
|
+
}
|
|
539
|
+
clearCachedUrl(activeEnv);
|
|
540
|
+
try {
|
|
541
|
+
const statusRes = await fetch(
|
|
542
|
+
`${STATUS_ENDPOINT}?environment=${activeEnv}`,
|
|
543
|
+
{ method: "GET", credentials: "include" }
|
|
544
|
+
);
|
|
545
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
546
|
+
setStatusInfo(refreshedStatus || null);
|
|
547
|
+
} catch {
|
|
548
|
+
}
|
|
549
|
+
setConnState("connected");
|
|
550
|
+
setShowManual(false);
|
|
551
|
+
} catch (e) {
|
|
552
|
+
completedRef.current = false;
|
|
553
|
+
console.error(e);
|
|
554
|
+
setConnState("error");
|
|
555
|
+
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
556
|
+
} finally {
|
|
557
|
+
setOnboardingInProgress(false);
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
[stopPopupPoll]
|
|
561
|
+
);
|
|
369
562
|
const fetchFreshLink = useCallback(
|
|
370
|
-
(runId) => {
|
|
563
|
+
(runId, targetEnv) => {
|
|
371
564
|
if (initLoaderRef.current) {
|
|
372
565
|
const loaderText = initLoaderRef.current.querySelector("#loader-text");
|
|
373
566
|
if (loaderText)
|
|
@@ -378,7 +571,10 @@ function PayPalConnectionPage() {
|
|
|
378
571
|
headers: { "content-type": "application/json" },
|
|
379
572
|
credentials: "include",
|
|
380
573
|
body: JSON.stringify({
|
|
381
|
-
products: ["PPCP"]
|
|
574
|
+
products: ["PPCP"],
|
|
575
|
+
// Generate the link for the explicitly selected environment so it can
|
|
576
|
+
// never depend on a racing POST /environment having landed yet.
|
|
577
|
+
environment: targetEnv
|
|
382
578
|
})
|
|
383
579
|
}).then((r) => {
|
|
384
580
|
if (!r.ok) throw new Error(`Service returned ${r.status}`);
|
|
@@ -391,10 +587,7 @@ function PayPalConnectionPage() {
|
|
|
391
587
|
return;
|
|
392
588
|
}
|
|
393
589
|
const url = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
|
|
394
|
-
|
|
395
|
-
CACHE_KEY,
|
|
396
|
-
JSON.stringify({ url, ts: Date.now() })
|
|
397
|
-
);
|
|
590
|
+
writeCachedUrl(targetEnv, url);
|
|
398
591
|
setFinalUrl(url);
|
|
399
592
|
setConnState("ready");
|
|
400
593
|
}).catch(() => {
|
|
@@ -402,8 +595,21 @@ function PayPalConnectionPage() {
|
|
|
402
595
|
showError("Unable to connect to service.");
|
|
403
596
|
});
|
|
404
597
|
},
|
|
405
|
-
[
|
|
598
|
+
[showError]
|
|
406
599
|
);
|
|
600
|
+
useEffect(() => {
|
|
601
|
+
let alive = true;
|
|
602
|
+
fetch(ENVIRONMENT_ENDPOINT, { method: "GET", credentials: "include" }).then((r) => r.json()).then((d) => {
|
|
603
|
+
if (!alive) return;
|
|
604
|
+
setEnv((d == null ? void 0 : d.environment) === "sandbox" ? "sandbox" : "live");
|
|
605
|
+
}).catch(() => {
|
|
606
|
+
}).finally(() => {
|
|
607
|
+
if (alive) setEnvReady(true);
|
|
608
|
+
});
|
|
609
|
+
return () => {
|
|
610
|
+
alive = false;
|
|
611
|
+
};
|
|
612
|
+
}, []);
|
|
407
613
|
useEffect(() => {
|
|
408
614
|
var _a, _b, _c;
|
|
409
615
|
if (connState !== "ready" || !finalUrl) return;
|
|
@@ -467,12 +673,26 @@ function PayPalConnectionPage() {
|
|
|
467
673
|
};
|
|
468
674
|
}, [connState, finalUrl, env]);
|
|
469
675
|
useEffect(() => {
|
|
676
|
+
const onMessage = (ev) => {
|
|
677
|
+
if (!isPayPalOrigin(ev.origin)) return;
|
|
678
|
+
const { authCode, sharedId } = extractAuth(ev.data);
|
|
679
|
+
if (authCode && sharedId) {
|
|
680
|
+
completeOnboarding(authCode, sharedId);
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
window.addEventListener("message", onMessage);
|
|
684
|
+
return () => window.removeEventListener("message", onMessage);
|
|
685
|
+
}, [completeOnboarding]);
|
|
686
|
+
useEffect(() => {
|
|
687
|
+
if (!envReady) return;
|
|
470
688
|
currentRunId.current = ++runIdRef.current;
|
|
471
689
|
const runId = currentRunId.current;
|
|
472
690
|
let cancelled = false;
|
|
691
|
+
completedRef.current = false;
|
|
473
692
|
const run = async () => {
|
|
474
693
|
setConnState("loading");
|
|
475
694
|
setError(null);
|
|
695
|
+
setPopupBlocked(false);
|
|
476
696
|
setFinalUrl("");
|
|
477
697
|
try {
|
|
478
698
|
const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
@@ -491,84 +711,46 @@ function PayPalConnectionPage() {
|
|
|
491
711
|
} catch (e) {
|
|
492
712
|
console.error(e);
|
|
493
713
|
}
|
|
494
|
-
if (
|
|
495
|
-
|
|
714
|
+
if (cancelled || runId !== currentRunId.current) return;
|
|
715
|
+
const cached = readCachedUrl(env);
|
|
716
|
+
if (cached) {
|
|
717
|
+
setFinalUrl(cached);
|
|
496
718
|
setConnState("ready");
|
|
497
719
|
} else {
|
|
498
|
-
fetchFreshLink(runId);
|
|
720
|
+
fetchFreshLink(runId, env);
|
|
499
721
|
}
|
|
500
722
|
};
|
|
501
723
|
run();
|
|
502
724
|
return () => {
|
|
503
725
|
cancelled = true;
|
|
504
|
-
currentRunId.current = 0;
|
|
505
726
|
};
|
|
506
|
-
}, [env, fetchFreshLink]);
|
|
727
|
+
}, [env, envReady, fetchFreshLink]);
|
|
507
728
|
useLayoutEffect(() => {
|
|
508
|
-
window.onboardingCallback =
|
|
509
|
-
|
|
510
|
-
try {
|
|
511
|
-
window.onbeforeunload = null;
|
|
512
|
-
} catch {
|
|
513
|
-
}
|
|
514
|
-
setOnboardingInProgress(true);
|
|
515
|
-
setConnState("loading");
|
|
516
|
-
setError(null);
|
|
517
|
-
const payload = {
|
|
518
|
-
authCode,
|
|
519
|
-
sharedId,
|
|
520
|
-
env: env === "sandbox" ? "sandbox" : "live"
|
|
521
|
-
};
|
|
522
|
-
try {
|
|
523
|
-
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
524
|
-
method: "POST",
|
|
525
|
-
headers: { "content-type": "application/json" },
|
|
526
|
-
credentials: "include",
|
|
527
|
-
body: JSON.stringify(payload)
|
|
528
|
-
});
|
|
529
|
-
if (!res.ok) {
|
|
530
|
-
const txt = await res.text().catch(() => "");
|
|
531
|
-
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
532
|
-
}
|
|
533
|
-
try {
|
|
534
|
-
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;
|
|
535
|
-
if (typeof close1 === "function") close1();
|
|
536
|
-
} catch {
|
|
537
|
-
}
|
|
538
|
-
try {
|
|
539
|
-
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;
|
|
540
|
-
if (typeof close2 === "function") close2();
|
|
541
|
-
} catch {
|
|
542
|
-
}
|
|
543
|
-
try {
|
|
544
|
-
localStorage.removeItem(CACHE_KEY);
|
|
545
|
-
} catch {
|
|
546
|
-
}
|
|
547
|
-
try {
|
|
548
|
-
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
549
|
-
method: "GET",
|
|
550
|
-
credentials: "include"
|
|
551
|
-
});
|
|
552
|
-
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
553
|
-
setStatusInfo(refreshedStatus || null);
|
|
554
|
-
setConnState("connected");
|
|
555
|
-
setShowManual(false);
|
|
556
|
-
} catch {
|
|
557
|
-
setConnState("connected");
|
|
558
|
-
setShowManual(false);
|
|
559
|
-
}
|
|
560
|
-
setOnboardingInProgress(false);
|
|
561
|
-
} catch (e) {
|
|
562
|
-
console.error(e);
|
|
563
|
-
setConnState("error");
|
|
564
|
-
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
565
|
-
setOnboardingInProgress(false);
|
|
566
|
-
}
|
|
729
|
+
window.onboardingCallback = (authCode, sharedId) => {
|
|
730
|
+
completeOnboarding(authCode, sharedId);
|
|
567
731
|
};
|
|
568
732
|
return () => {
|
|
569
733
|
window.onboardingCallback = void 0;
|
|
570
734
|
};
|
|
571
|
-
}, [
|
|
735
|
+
}, [completeOnboarding]);
|
|
736
|
+
useEffect(() => {
|
|
737
|
+
return () => {
|
|
738
|
+
stopPopupPoll();
|
|
739
|
+
};
|
|
740
|
+
}, [stopPopupPoll]);
|
|
741
|
+
useEffect(() => {
|
|
742
|
+
const onCaptureClick = (e) => {
|
|
743
|
+
const btn = paypalButtonRef.current;
|
|
744
|
+
if (!btn) return;
|
|
745
|
+
const target = e.target;
|
|
746
|
+
if (!target || !btn.contains(target)) return;
|
|
747
|
+
e.preventDefault();
|
|
748
|
+
e.stopImmediatePropagation();
|
|
749
|
+
openConnect();
|
|
750
|
+
};
|
|
751
|
+
document.addEventListener("click", onCaptureClick, true);
|
|
752
|
+
return () => document.removeEventListener("click", onCaptureClick, true);
|
|
753
|
+
}, [openConnect]);
|
|
572
754
|
useLayoutEffect(() => {
|
|
573
755
|
const el = ppBtnMeasureRef.current;
|
|
574
756
|
if (!el) return;
|
|
@@ -590,9 +772,8 @@ function PayPalConnectionPage() {
|
|
|
590
772
|
};
|
|
591
773
|
}, [connState, env, finalUrl]);
|
|
592
774
|
const handleConnectClick = (e) => {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
775
|
+
e.preventDefault();
|
|
776
|
+
openConnect();
|
|
596
777
|
};
|
|
597
778
|
const handleSaveManual = async () => {
|
|
598
779
|
if (!canSaveManual || onboardingInProgress) return;
|
|
@@ -622,10 +803,7 @@ function PayPalConnectionPage() {
|
|
|
622
803
|
setConnState("connected");
|
|
623
804
|
setStatusInfo(refreshedStatus || null);
|
|
624
805
|
setShowManual(false);
|
|
625
|
-
|
|
626
|
-
localStorage.removeItem(CACHE_KEY);
|
|
627
|
-
} catch {
|
|
628
|
-
}
|
|
806
|
+
clearCachedUrl(env);
|
|
629
807
|
} catch (e) {
|
|
630
808
|
console.error(e);
|
|
631
809
|
setConnState("error");
|
|
@@ -654,13 +832,11 @@ function PayPalConnectionPage() {
|
|
|
654
832
|
const t = await res.text().catch(() => "");
|
|
655
833
|
throw new Error(t || `Disconnect failed (${res.status})`);
|
|
656
834
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
} catch {
|
|
660
|
-
}
|
|
835
|
+
clearCachedUrl(env);
|
|
836
|
+
completedRef.current = false;
|
|
661
837
|
currentRunId.current = ++runIdRef.current;
|
|
662
838
|
const runId = currentRunId.current;
|
|
663
|
-
fetchFreshLink(runId);
|
|
839
|
+
fetchFreshLink(runId, env);
|
|
664
840
|
} catch (e) {
|
|
665
841
|
console.error(e);
|
|
666
842
|
setConnState("error");
|
|
@@ -671,10 +847,12 @@ function PayPalConnectionPage() {
|
|
|
671
847
|
};
|
|
672
848
|
const handleEnvChange = async (e) => {
|
|
673
849
|
const next = e.target.value;
|
|
850
|
+
completedRef.current = false;
|
|
851
|
+
setPopupBlocked(false);
|
|
852
|
+
clearCachedUrl();
|
|
674
853
|
setEnv(next);
|
|
675
|
-
cachedUrl = null;
|
|
676
854
|
try {
|
|
677
|
-
await fetch(
|
|
855
|
+
await fetch(ENVIRONMENT_ENDPOINT, {
|
|
678
856
|
method: "POST",
|
|
679
857
|
headers: { "content-type": "application/json" },
|
|
680
858
|
credentials: "include",
|
|
@@ -682,10 +860,6 @@ function PayPalConnectionPage() {
|
|
|
682
860
|
});
|
|
683
861
|
} catch {
|
|
684
862
|
}
|
|
685
|
-
try {
|
|
686
|
-
localStorage.removeItem(CACHE_KEY);
|
|
687
|
-
} catch {
|
|
688
|
-
}
|
|
689
863
|
};
|
|
690
864
|
return /* @__PURE__ */ jsxs("div", { className: "p-6", children: [
|
|
691
865
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
@@ -749,7 +923,7 @@ function PayPalConnectionPage() {
|
|
|
749
923
|
ppBtnMeasureRef.current = node;
|
|
750
924
|
},
|
|
751
925
|
id: "paypal-button",
|
|
752
|
-
target:
|
|
926
|
+
target: POPUP_NAME,
|
|
753
927
|
"data-paypal-button": "true",
|
|
754
928
|
href: finalUrl || "#",
|
|
755
929
|
"data-paypal-onboard-complete": "onboardingCallback",
|
|
@@ -763,6 +937,7 @@ function PayPalConnectionPage() {
|
|
|
763
937
|
children: "Connect to PayPal"
|
|
764
938
|
}
|
|
765
939
|
),
|
|
940
|
+
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." }),
|
|
766
941
|
/* @__PURE__ */ jsx(
|
|
767
942
|
"div",
|
|
768
943
|
{
|
|
@@ -918,12 +1093,6 @@ function PayPalConnectionPage() {
|
|
|
918
1093
|
` })
|
|
919
1094
|
] });
|
|
920
1095
|
}
|
|
921
|
-
function PayPalApplePayPage() {
|
|
922
|
-
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
923
|
-
}
|
|
924
|
-
function PayPalGooglePayPage() {
|
|
925
|
-
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
926
|
-
}
|
|
927
1096
|
function PayPalPayLaterMessagingPage() {
|
|
928
1097
|
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
929
1098
|
}
|
|
@@ -1149,10 +1318,6 @@ const routeModule = {
|
|
|
1149
1318
|
Component: AdvancedCardPaymentsTab,
|
|
1150
1319
|
path: "/settings/paypal/advanced-card-payments"
|
|
1151
1320
|
},
|
|
1152
|
-
{
|
|
1153
|
-
Component: PayPalConnectionPage,
|
|
1154
|
-
path: "/settings/paypal/connection"
|
|
1155
|
-
},
|
|
1156
1321
|
{
|
|
1157
1322
|
Component: PayPalApplePayPage,
|
|
1158
1323
|
path: "/settings/paypal/apple-pay"
|
|
@@ -1161,6 +1326,10 @@ const routeModule = {
|
|
|
1161
1326
|
Component: PayPalGooglePayPage,
|
|
1162
1327
|
path: "/settings/paypal/google-pay"
|
|
1163
1328
|
},
|
|
1329
|
+
{
|
|
1330
|
+
Component: PayPalConnectionPage,
|
|
1331
|
+
path: "/settings/paypal/connection"
|
|
1332
|
+
},
|
|
1164
1333
|
{
|
|
1165
1334
|
Component: PayPalPayLaterMessagingPage,
|
|
1166
1335
|
path: "/settings/paypal/pay-later-messaging"
|
|
@@ -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;
|
|
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;AAmID,MAAM,CAAC,OAAO,UAAU,oBAAoB,4CAy2B3C"}
|