@easypayment/medusa-payment-paypal 0.9.24 → 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.
- package/.medusa/server/src/admin/index.js +187 -287
- package/.medusa/server/src/admin/index.mjs +187 -287
- package/.medusa/server/src/admin/routes/settings/paypal/connection/page.d.ts +0 -1
- 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 +204 -332
- package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js.map +1 -1
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts +7 -0
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts.map +1 -1
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js +7 -0
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/onboard-return/route.d.ts +25 -0
- package/.medusa/server/src/api/store/paypal/onboard-return/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal/onboard-return/route.js +82 -0
- package/.medusa/server/src/api/store/paypal/onboard-return/route.js.map +1 -0
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +32 -2
- 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 +230 -354
- package/src/api/admin/paypal/onboard-complete/route.ts +7 -0
- package/src/api/store/paypal/onboard-return/route.ts +88 -0
- package/src/modules/paypal/service.ts +34 -3
|
@@ -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,15 +308,17 @@ function AdvancedCardPaymentsTab() {
|
|
|
311
308
|
)
|
|
312
309
|
] }) });
|
|
313
310
|
}
|
|
311
|
+
function PayPalGooglePayPage() {
|
|
312
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
313
|
+
}
|
|
314
|
+
function PayPalApplePayPage() {
|
|
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
|
});
|
|
317
|
-
const
|
|
318
|
-
sandbox: "https://www.sandbox.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js",
|
|
319
|
-
live: "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js"
|
|
320
|
-
};
|
|
320
|
+
const PARTNER_JS_URL = "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js";
|
|
321
321
|
const SERVICE_URL = "/admin/paypal/onboarding-link";
|
|
322
|
-
const POPUP_NAME = "PPFrame";
|
|
323
322
|
const CACHE_PREFIX = "pp_onboard_cache";
|
|
324
323
|
const CACHE_EXPIRY = 6 * 60 * 60 * 1e3;
|
|
325
324
|
const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
|
|
@@ -344,9 +343,7 @@ function readCachedUrl(env) {
|
|
|
344
343
|
function writeCachedUrl(env, url) {
|
|
345
344
|
try {
|
|
346
345
|
localStorage.setItem(cacheKeyFor(env), JSON.stringify({ url, ts: Date.now() }));
|
|
347
|
-
return readCachedUrl(env) === url;
|
|
348
346
|
} catch {
|
|
349
|
-
return false;
|
|
350
347
|
}
|
|
351
348
|
}
|
|
352
349
|
function clearCachedUrl(env) {
|
|
@@ -360,62 +357,11 @@ function clearCachedUrl(env) {
|
|
|
360
357
|
} catch {
|
|
361
358
|
}
|
|
362
359
|
}
|
|
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 ?? obj.code;
|
|
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", "params"]) {
|
|
381
|
-
if (obj[key] && typeof obj[key] === "object") {
|
|
382
|
-
const inner = extractAuth(obj[key]);
|
|
383
|
-
if (inner.authCode && inner.sharedId) return inner;
|
|
384
|
-
}
|
|
385
|
-
if (typeof obj[key] === "string") {
|
|
386
|
-
const inner = extractAuth(obj[key]);
|
|
387
|
-
if (inner.authCode && inner.sharedId) return inner;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
return {};
|
|
391
|
-
}
|
|
392
|
-
if (typeof data === "string") {
|
|
393
|
-
const s = data.trim();
|
|
394
|
-
if (!s) return {};
|
|
395
|
-
if (s.startsWith("{") || s.startsWith("[")) {
|
|
396
|
-
try {
|
|
397
|
-
return extractAuth(JSON.parse(s));
|
|
398
|
-
} catch {
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (/auth_?code/i.test(s) && /shared_?id/i.test(s)) {
|
|
402
|
-
try {
|
|
403
|
-
const sp = new URLSearchParams(s.replace(/^[?#]/, ""));
|
|
404
|
-
const authCode = sp.get("authCode") || sp.get("auth_code") || void 0;
|
|
405
|
-
const sharedId = sp.get("sharedId") || sp.get("shared_id") || void 0;
|
|
406
|
-
if (authCode && sharedId) return { authCode, sharedId };
|
|
407
|
-
} catch {
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
return {};
|
|
412
|
-
}
|
|
413
360
|
function PayPalConnectionPage() {
|
|
414
361
|
const [env, setEnv] = react.useState("live");
|
|
415
362
|
const [envReady, setEnvReady] = react.useState(false);
|
|
416
363
|
const [connState, setConnState] = react.useState("loading");
|
|
417
364
|
const [error, setError] = react.useState(null);
|
|
418
|
-
const [popupBlocked, setPopupBlocked] = react.useState(false);
|
|
419
365
|
const [finalUrl, setFinalUrl] = react.useState("");
|
|
420
366
|
const [showManual, setShowManual] = react.useState(false);
|
|
421
367
|
const [clientId, setClientId] = react.useState("");
|
|
@@ -427,17 +373,11 @@ function PayPalConnectionPage() {
|
|
|
427
373
|
const errorLogRef = react.useRef(null);
|
|
428
374
|
const runIdRef = react.useRef(0);
|
|
429
375
|
const currentRunId = react.useRef(0);
|
|
376
|
+
const completedRef = react.useRef(false);
|
|
430
377
|
const envRef = react.useRef(env);
|
|
431
378
|
envRef.current = env;
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
const connStateRef = react.useRef(connState);
|
|
435
|
-
connStateRef.current = connState;
|
|
436
|
-
const inProgressRef = react.useRef(onboardingInProgress);
|
|
437
|
-
inProgressRef.current = onboardingInProgress;
|
|
438
|
-
const popupRef = react.useRef(null);
|
|
439
|
-
const pollRef = react.useRef(null);
|
|
440
|
-
const completedRef = react.useRef(false);
|
|
379
|
+
const pollTimerRef = react.useRef(null);
|
|
380
|
+
const pollAttemptsRef = react.useRef(0);
|
|
441
381
|
const ppBtnMeasureRef = react.useRef(null);
|
|
442
382
|
const [ppBtnWidth, setPpBtnWidth] = react.useState(null);
|
|
443
383
|
const canSaveManual = react.useMemo(() => {
|
|
@@ -447,44 +387,72 @@ function PayPalConnectionPage() {
|
|
|
447
387
|
setConnState("error");
|
|
448
388
|
setError(msg);
|
|
449
389
|
}, []);
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
390
|
+
const closeMiniBrowser = react.useCallback(() => {
|
|
391
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
392
|
+
try {
|
|
393
|
+
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;
|
|
394
|
+
if (typeof close1 === "function") close1();
|
|
395
|
+
} catch {
|
|
454
396
|
}
|
|
455
|
-
}, []);
|
|
456
|
-
const openOnboardingPopup = react.useCallback((url) => {
|
|
457
|
-
const w = 450;
|
|
458
|
-
const h = 600;
|
|
459
|
-
const baseLeft = typeof window.screenX === "number" ? window.screenX : window.screenLeft || 0;
|
|
460
|
-
const baseTop = typeof window.screenY === "number" ? window.screenY : window.screenTop || 0;
|
|
461
|
-
const outerW = window.outerWidth || document.documentElement.clientWidth || 1024;
|
|
462
|
-
const outerH = window.outerHeight || document.documentElement.clientHeight || 768;
|
|
463
|
-
const left = Math.round(baseLeft + Math.max(0, (outerW - w) / 2));
|
|
464
|
-
const top = Math.round(baseTop + Math.max(0, (outerH - h) / 2));
|
|
465
|
-
const features = `popup=yes,width=${w},height=${h},left=${left},top=${top},scrollbars=yes,resizable=yes`;
|
|
466
|
-
let popup = null;
|
|
467
397
|
try {
|
|
468
|
-
|
|
398
|
+
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;
|
|
399
|
+
if (typeof close2 === "function") close2();
|
|
469
400
|
} catch {
|
|
470
|
-
popup = null;
|
|
471
401
|
}
|
|
472
|
-
|
|
473
|
-
|
|
402
|
+
}, []);
|
|
403
|
+
const stopStatusPolling = react.useCallback(() => {
|
|
404
|
+
if (pollTimerRef.current) {
|
|
405
|
+
clearTimeout(pollTimerRef.current);
|
|
406
|
+
pollTimerRef.current = null;
|
|
407
|
+
}
|
|
408
|
+
pollAttemptsRef.current = 0;
|
|
409
|
+
}, []);
|
|
410
|
+
const refreshStatusAndMaybeConnect = react.useCallback(
|
|
411
|
+
async (activeEnv) => {
|
|
474
412
|
try {
|
|
475
|
-
|
|
413
|
+
const res = await fetch(`${STATUS_ENDPOINT}?environment=${activeEnv}`, {
|
|
414
|
+
method: "GET",
|
|
415
|
+
credentials: "include"
|
|
416
|
+
});
|
|
417
|
+
const st = await res.json().catch(() => ({}));
|
|
418
|
+
const connected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
|
|
419
|
+
if (connected) {
|
|
420
|
+
completedRef.current = true;
|
|
421
|
+
setStatusInfo(st);
|
|
422
|
+
setConnState("connected");
|
|
423
|
+
setShowManual(false);
|
|
424
|
+
setOnboardingInProgress(false);
|
|
425
|
+
clearCachedUrl(activeEnv);
|
|
426
|
+
closeMiniBrowser();
|
|
427
|
+
stopStatusPolling();
|
|
428
|
+
}
|
|
429
|
+
return connected;
|
|
476
430
|
} catch {
|
|
431
|
+
return false;
|
|
477
432
|
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
|
|
433
|
+
},
|
|
434
|
+
[closeMiniBrowser, stopStatusPolling]
|
|
435
|
+
);
|
|
436
|
+
const startStatusPolling = react.useCallback(() => {
|
|
437
|
+
stopStatusPolling();
|
|
438
|
+
const MAX_ATTEMPTS = 100;
|
|
439
|
+
const tick = async () => {
|
|
440
|
+
pollAttemptsRef.current += 1;
|
|
441
|
+
const connected = await refreshStatusAndMaybeConnect(envRef.current);
|
|
442
|
+
if (connected || completedRef.current) return;
|
|
443
|
+
if (pollAttemptsRef.current >= MAX_ATTEMPTS) {
|
|
444
|
+
stopStatusPolling();
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
pollTimerRef.current = setTimeout(tick, 3e3);
|
|
448
|
+
};
|
|
449
|
+
pollTimerRef.current = setTimeout(tick, 3e3);
|
|
450
|
+
}, [refreshStatusAndMaybeConnect, stopStatusPolling]);
|
|
481
451
|
const completeOnboarding = react.useCallback(
|
|
482
452
|
async (authCode, sharedId) => {
|
|
483
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
484
453
|
if (!authCode || !sharedId) return;
|
|
485
454
|
if (completedRef.current) return;
|
|
486
455
|
completedRef.current = true;
|
|
487
|
-
stopPoll();
|
|
488
456
|
try {
|
|
489
457
|
window.onbeforeunload = null;
|
|
490
458
|
} catch {
|
|
@@ -493,7 +461,6 @@ function PayPalConnectionPage() {
|
|
|
493
461
|
setOnboardingInProgress(true);
|
|
494
462
|
setConnState("loading");
|
|
495
463
|
setError(null);
|
|
496
|
-
setPopupBlocked(false);
|
|
497
464
|
try {
|
|
498
465
|
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
499
466
|
method: "POST",
|
|
@@ -505,32 +472,20 @@ function PayPalConnectionPage() {
|
|
|
505
472
|
const txt = await res.text().catch(() => "");
|
|
506
473
|
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
507
474
|
}
|
|
508
|
-
|
|
509
|
-
(_a = popupRef.current) == null ? void 0 : _a.close();
|
|
510
|
-
} catch {
|
|
511
|
-
}
|
|
512
|
-
try {
|
|
513
|
-
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;
|
|
514
|
-
if (typeof close1 === "function") close1();
|
|
515
|
-
} catch {
|
|
516
|
-
}
|
|
517
|
-
try {
|
|
518
|
-
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;
|
|
519
|
-
if (typeof close2 === "function") close2();
|
|
520
|
-
} catch {
|
|
521
|
-
}
|
|
475
|
+
closeMiniBrowser();
|
|
522
476
|
clearCachedUrl(activeEnv);
|
|
523
477
|
try {
|
|
524
|
-
const statusRes = await fetch(
|
|
525
|
-
|
|
526
|
-
credentials: "include"
|
|
527
|
-
|
|
478
|
+
const statusRes = await fetch(
|
|
479
|
+
`${STATUS_ENDPOINT}?environment=${activeEnv}`,
|
|
480
|
+
{ method: "GET", credentials: "include" }
|
|
481
|
+
);
|
|
528
482
|
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
529
483
|
setStatusInfo(refreshedStatus || null);
|
|
530
484
|
} catch {
|
|
531
485
|
}
|
|
532
486
|
setConnState("connected");
|
|
533
487
|
setShowManual(false);
|
|
488
|
+
stopStatusPolling();
|
|
534
489
|
} catch (e) {
|
|
535
490
|
completedRef.current = false;
|
|
536
491
|
console.error(e);
|
|
@@ -540,42 +495,72 @@ function PayPalConnectionPage() {
|
|
|
540
495
|
setOnboardingInProgress(false);
|
|
541
496
|
}
|
|
542
497
|
},
|
|
543
|
-
[
|
|
498
|
+
[closeMiniBrowser, stopStatusPolling]
|
|
544
499
|
);
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
ticks += 1;
|
|
551
|
-
if (completedRef.current || ticks > 150) {
|
|
552
|
-
stopPoll();
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
500
|
+
const initPartner = react.useCallback(() => {
|
|
501
|
+
var _a, _b;
|
|
502
|
+
const signup = (_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup;
|
|
503
|
+
const init = (signup == null ? void 0 : signup.miniBrowser) && signup.miniBrowser.init || (signup == null ? void 0 : signup.MiniBrowser) && signup.MiniBrowser.init;
|
|
504
|
+
if (typeof init === "function") {
|
|
555
505
|
try {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
506
|
+
init();
|
|
507
|
+
} catch (e) {
|
|
508
|
+
console.error("[paypal] partner.js init failed:", e);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}, []);
|
|
512
|
+
react.useEffect(() => {
|
|
513
|
+
const existingScript = document.getElementById("paypal-partner-js");
|
|
514
|
+
if (existingScript) return;
|
|
515
|
+
const preloadHref = PARTNER_JS_URL;
|
|
516
|
+
let preloadLink = null;
|
|
517
|
+
if (!document.head.querySelector(`link[rel="preload"][href="${preloadHref}"]`)) {
|
|
518
|
+
preloadLink = document.createElement("link");
|
|
519
|
+
preloadLink.rel = "preload";
|
|
520
|
+
preloadLink.href = preloadHref;
|
|
521
|
+
preloadLink.as = "script";
|
|
522
|
+
document.head.appendChild(preloadLink);
|
|
523
|
+
}
|
|
524
|
+
const ppScript = document.createElement("script");
|
|
525
|
+
ppScript.id = "paypal-partner-js";
|
|
526
|
+
ppScript.src = preloadHref;
|
|
527
|
+
ppScript.async = true;
|
|
528
|
+
document.head.appendChild(ppScript);
|
|
529
|
+
return () => {
|
|
530
|
+
if (preloadLink == null ? void 0 : preloadLink.parentNode) preloadLink.parentNode.removeChild(preloadLink);
|
|
531
|
+
if (ppScript.parentNode) ppScript.parentNode.removeChild(ppScript);
|
|
532
|
+
};
|
|
533
|
+
}, []);
|
|
534
|
+
const activatePayPal = react.useCallback(
|
|
535
|
+
(url, runId) => {
|
|
536
|
+
if (paypalButtonRef.current) {
|
|
537
|
+
paypalButtonRef.current.href = url;
|
|
575
538
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
539
|
+
setFinalUrl(url);
|
|
540
|
+
let attempts = 0;
|
|
541
|
+
const MAX_ATTEMPTS = 200;
|
|
542
|
+
const tryInit = () => {
|
|
543
|
+
var _a, _b;
|
|
544
|
+
if (runId !== currentRunId.current) return;
|
|
545
|
+
if ((_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) {
|
|
546
|
+
initPartner();
|
|
547
|
+
setConnState("ready");
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
attempts++;
|
|
551
|
+
if (attempts >= MAX_ATTEMPTS) {
|
|
552
|
+
showError(
|
|
553
|
+
"PayPal partner script failed to load. Please refresh and try again."
|
|
554
|
+
);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
setTimeout(tryInit, 50);
|
|
558
|
+
};
|
|
559
|
+
tryInit();
|
|
560
|
+
},
|
|
561
|
+
[initPartner, showError]
|
|
562
|
+
);
|
|
563
|
+
const fetchFreshLink = react.useCallback(
|
|
579
564
|
async (targetEnv, runId) => {
|
|
580
565
|
if (initLoaderRef.current) {
|
|
581
566
|
const loaderText = initLoaderRef.current.querySelector("#loader-text");
|
|
@@ -597,19 +582,14 @@ function PayPalConnectionPage() {
|
|
|
597
582
|
return;
|
|
598
583
|
}
|
|
599
584
|
const url = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
window.location.reload();
|
|
603
|
-
return;
|
|
604
|
-
}
|
|
605
|
-
setFinalUrl(url);
|
|
606
|
-
setConnState("ready");
|
|
585
|
+
writeCachedUrl(targetEnv, url);
|
|
586
|
+
activatePayPal(url, runId);
|
|
607
587
|
} catch {
|
|
608
588
|
if (runId !== currentRunId.current) return;
|
|
609
589
|
showError("Unable to connect to service.");
|
|
610
590
|
}
|
|
611
591
|
},
|
|
612
|
-
[showError]
|
|
592
|
+
[activatePayPal, showError]
|
|
613
593
|
);
|
|
614
594
|
react.useEffect(() => {
|
|
615
595
|
let alive = true;
|
|
@@ -633,7 +613,6 @@ function PayPalConnectionPage() {
|
|
|
633
613
|
const run = async () => {
|
|
634
614
|
setConnState("loading");
|
|
635
615
|
setError(null);
|
|
636
|
-
setPopupBlocked(false);
|
|
637
616
|
setFinalUrl("");
|
|
638
617
|
try {
|
|
639
618
|
const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
@@ -655,135 +634,43 @@ function PayPalConnectionPage() {
|
|
|
655
634
|
if (cancelled || runId !== currentRunId.current) return;
|
|
656
635
|
const cached = readCachedUrl(env);
|
|
657
636
|
if (cached) {
|
|
658
|
-
|
|
659
|
-
setConnState("ready");
|
|
637
|
+
activatePayPal(cached, runId);
|
|
660
638
|
return;
|
|
661
639
|
}
|
|
662
|
-
await
|
|
640
|
+
await fetchFreshLink(env, runId);
|
|
663
641
|
};
|
|
664
642
|
run();
|
|
665
643
|
return () => {
|
|
666
644
|
cancelled = true;
|
|
667
645
|
};
|
|
668
|
-
}, [env, envReady,
|
|
669
|
-
react.useEffect(() => {
|
|
670
|
-
var _a, _b, _c;
|
|
671
|
-
if (connState !== "ready" || !finalUrl) return;
|
|
672
|
-
const scriptUrl = PARTNER_JS_URLS[env];
|
|
673
|
-
let cancelled = false;
|
|
674
|
-
let pollTimer;
|
|
675
|
-
const initPartner = (attempt = 0) => {
|
|
676
|
-
var _a2, _b2;
|
|
677
|
-
if (cancelled) return;
|
|
678
|
-
const signup = (_b2 = (_a2 = window.PAYPAL) == null ? void 0 : _a2.apps) == null ? void 0 : _b2.Signup;
|
|
679
|
-
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;
|
|
680
|
-
if (target == null ? void 0 : target.init) {
|
|
681
|
-
try {
|
|
682
|
-
target.init();
|
|
683
|
-
} catch (e) {
|
|
684
|
-
console.error("[paypal] partner.js init failed:", e);
|
|
685
|
-
}
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
if (typeof (signup == null ? void 0 : signup.render) === "function") {
|
|
689
|
-
try {
|
|
690
|
-
signup.render();
|
|
691
|
-
} catch (e) {
|
|
692
|
-
console.error("[paypal] partner.js render failed:", e);
|
|
693
|
-
}
|
|
694
|
-
return;
|
|
695
|
-
}
|
|
696
|
-
if (attempt < 40) {
|
|
697
|
-
pollTimer = setTimeout(() => initPartner(attempt + 1), 50);
|
|
698
|
-
return;
|
|
699
|
-
}
|
|
700
|
-
try {
|
|
701
|
-
document.dispatchEvent(new Event("DOMContentLoaded"));
|
|
702
|
-
} catch {
|
|
703
|
-
}
|
|
704
|
-
};
|
|
705
|
-
const existingScript = document.getElementById("paypal-partner-js");
|
|
706
|
-
if (existingScript) {
|
|
707
|
-
(_a = existingScript.parentNode) == null ? void 0 : _a.removeChild(existingScript);
|
|
708
|
-
}
|
|
709
|
-
if ((_c = (_b = window.PAYPAL) == null ? void 0 : _b.apps) == null ? void 0 : _c.Signup) {
|
|
710
|
-
try {
|
|
711
|
-
delete window.PAYPAL.apps.Signup;
|
|
712
|
-
} catch {
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
const ppScript = document.createElement("script");
|
|
716
|
-
ppScript.id = "paypal-partner-js";
|
|
717
|
-
ppScript.src = scriptUrl;
|
|
718
|
-
ppScript.async = true;
|
|
719
|
-
ppScript.onload = () => initPartner();
|
|
720
|
-
document.body.appendChild(ppScript);
|
|
721
|
-
return () => {
|
|
722
|
-
cancelled = true;
|
|
723
|
-
if (pollTimer) clearTimeout(pollTimer);
|
|
724
|
-
if (ppScript.parentNode) ppScript.parentNode.removeChild(ppScript);
|
|
725
|
-
};
|
|
726
|
-
}, [connState, finalUrl, env]);
|
|
727
|
-
react.useEffect(() => {
|
|
728
|
-
const onMessage = (ev) => {
|
|
729
|
-
let serialized = "";
|
|
730
|
-
try {
|
|
731
|
-
serialized = typeof ev.data === "string" ? ev.data : JSON.stringify(ev.data);
|
|
732
|
-
} catch {
|
|
733
|
-
serialized = String(ev.data);
|
|
734
|
-
}
|
|
735
|
-
const looksRelevant = isPayPalOrigin(ev.origin) || /auth_?code|shared_?id|onboard|merchantId/i.test(serialized || "");
|
|
736
|
-
if (looksRelevant) {
|
|
737
|
-
console.info(
|
|
738
|
-
"[PayPal onboarding] message from",
|
|
739
|
-
ev.origin,
|
|
740
|
-
"·",
|
|
741
|
-
(serialized || "").slice(0, 500)
|
|
742
|
-
);
|
|
743
|
-
}
|
|
744
|
-
if (!isPayPalOrigin(ev.origin)) return;
|
|
745
|
-
const { authCode, sharedId } = extractAuth(ev.data);
|
|
746
|
-
if (authCode && sharedId) {
|
|
747
|
-
completeOnboarding(authCode, sharedId);
|
|
748
|
-
}
|
|
749
|
-
};
|
|
750
|
-
window.addEventListener("message", onMessage);
|
|
751
|
-
return () => window.removeEventListener("message", onMessage);
|
|
752
|
-
}, [completeOnboarding]);
|
|
646
|
+
}, [env, envReady, fetchFreshLink, activatePayPal]);
|
|
753
647
|
react.useLayoutEffect(() => {
|
|
754
648
|
window.onboardingCallback = (authCode, sharedId) => {
|
|
755
|
-
completeOnboarding(authCode, sharedId);
|
|
649
|
+
void completeOnboarding(authCode, sharedId);
|
|
756
650
|
};
|
|
757
651
|
return () => {
|
|
758
652
|
window.onboardingCallback = void 0;
|
|
759
653
|
};
|
|
760
654
|
}, [completeOnboarding]);
|
|
761
655
|
react.useEffect(() => {
|
|
762
|
-
const
|
|
763
|
-
const
|
|
764
|
-
if (!
|
|
765
|
-
const
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
setPopupBlocked(true);
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
setPopupBlocked(false);
|
|
779
|
-
startStatusPoll();
|
|
656
|
+
const onMessage = (event) => {
|
|
657
|
+
const data = event == null ? void 0 : event.data;
|
|
658
|
+
if (!data || data.source !== "paypal-onboarding-return") return;
|
|
659
|
+
const params = data.params || {};
|
|
660
|
+
const authCode = params.authCode || params.auth_code;
|
|
661
|
+
const sharedId = params.sharedId || params.shared_id;
|
|
662
|
+
const activeEnv = envRef.current;
|
|
663
|
+
void (async () => {
|
|
664
|
+
const connected = await refreshStatusAndMaybeConnect(activeEnv);
|
|
665
|
+
if (!connected && authCode && sharedId) {
|
|
666
|
+
await completeOnboarding(authCode, sharedId);
|
|
667
|
+
}
|
|
668
|
+
})();
|
|
780
669
|
};
|
|
781
|
-
|
|
782
|
-
return () =>
|
|
783
|
-
}, [
|
|
784
|
-
react.useEffect(() =>
|
|
785
|
-
return () => stopPoll();
|
|
786
|
-
}, [stopPoll]);
|
|
670
|
+
window.addEventListener("message", onMessage);
|
|
671
|
+
return () => window.removeEventListener("message", onMessage);
|
|
672
|
+
}, [completeOnboarding, refreshStatusAndMaybeConnect]);
|
|
673
|
+
react.useEffect(() => stopStatusPolling, [stopStatusPolling]);
|
|
787
674
|
react.useLayoutEffect(() => {
|
|
788
675
|
const el = ppBtnMeasureRef.current;
|
|
789
676
|
if (!el) return;
|
|
@@ -805,7 +692,12 @@ function PayPalConnectionPage() {
|
|
|
805
692
|
};
|
|
806
693
|
}, [connState, env, finalUrl]);
|
|
807
694
|
const handleConnectClick = (e) => {
|
|
808
|
-
|
|
695
|
+
if (connState !== "ready" || !finalUrl || onboardingInProgress) {
|
|
696
|
+
e.preventDefault();
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
completedRef.current = false;
|
|
700
|
+
startStatusPolling();
|
|
809
701
|
};
|
|
810
702
|
const handleSaveManual = async () => {
|
|
811
703
|
if (!canSaveManual || onboardingInProgress) return;
|
|
@@ -847,6 +739,7 @@ function PayPalConnectionPage() {
|
|
|
847
739
|
const handleDisconnect = async () => {
|
|
848
740
|
if (onboardingInProgress) return;
|
|
849
741
|
if (!window.confirm("Disconnect PayPal for this environment?")) return;
|
|
742
|
+
stopStatusPolling();
|
|
850
743
|
setOnboardingInProgress(true);
|
|
851
744
|
setConnState("loading");
|
|
852
745
|
setError(null);
|
|
@@ -867,7 +760,7 @@ function PayPalConnectionPage() {
|
|
|
867
760
|
clearCachedUrl(env);
|
|
868
761
|
completedRef.current = false;
|
|
869
762
|
currentRunId.current = ++runIdRef.current;
|
|
870
|
-
await
|
|
763
|
+
await fetchFreshLink(env, currentRunId.current);
|
|
871
764
|
} catch (e) {
|
|
872
765
|
console.error(e);
|
|
873
766
|
setConnState("error");
|
|
@@ -879,9 +772,9 @@ function PayPalConnectionPage() {
|
|
|
879
772
|
const handleEnvChange = async (e) => {
|
|
880
773
|
const next = e.target.value;
|
|
881
774
|
if (next === env || onboardingInProgress) return;
|
|
775
|
+
stopStatusPolling();
|
|
882
776
|
completedRef.current = false;
|
|
883
777
|
clearCachedUrl();
|
|
884
|
-
setPopupBlocked(false);
|
|
885
778
|
setConnState("loading");
|
|
886
779
|
try {
|
|
887
780
|
await fetch(ENVIRONMENT_ENDPOINT, {
|
|
@@ -915,7 +808,19 @@ function PayPalConnectionPage() {
|
|
|
915
808
|
) }),
|
|
916
809
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium pt-2", children: env === "sandbox" ? "Connect to PayPal (Sandbox)" : "Connect to PayPal" }),
|
|
917
810
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xl", children: connState === "connected" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
918
|
-
/* @__PURE__ */ jsxRuntime.
|
|
811
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-green-600 bg-green-50 p-3 rounded border border-green-200", children: [
|
|
812
|
+
"✅ Successfully connected to PayPal!",
|
|
813
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
814
|
+
"a",
|
|
815
|
+
{
|
|
816
|
+
"data-paypal-button": "true",
|
|
817
|
+
"data-paypal-onboard-complete": "onboardingCallback",
|
|
818
|
+
href: "#",
|
|
819
|
+
style: { display: "none" },
|
|
820
|
+
children: "PayPal"
|
|
821
|
+
}
|
|
822
|
+
)
|
|
823
|
+
] }),
|
|
919
824
|
/* @__PURE__ */ jsxRuntime.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: [
|
|
920
825
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-ui-fg-base", children: "Connected PayPal account" }),
|
|
921
826
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1", children: [
|
|
@@ -956,7 +861,6 @@ function PayPalConnectionPage() {
|
|
|
956
861
|
ppBtnMeasureRef.current = node;
|
|
957
862
|
},
|
|
958
863
|
id: "paypal-button",
|
|
959
|
-
target: POPUP_NAME,
|
|
960
864
|
"data-paypal-button": "true",
|
|
961
865
|
href: finalUrl || "#",
|
|
962
866
|
"data-paypal-onboard-complete": "onboardingCallback",
|
|
@@ -970,7 +874,6 @@ function PayPalConnectionPage() {
|
|
|
970
874
|
children: "Connect to PayPal"
|
|
971
875
|
}
|
|
972
876
|
),
|
|
973
|
-
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." }),
|
|
974
877
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
975
878
|
"div",
|
|
976
879
|
{
|
|
@@ -1126,9 +1029,6 @@ function PayPalConnectionPage() {
|
|
|
1126
1029
|
` })
|
|
1127
1030
|
] });
|
|
1128
1031
|
}
|
|
1129
|
-
function PayPalGooglePayPage() {
|
|
1130
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1131
|
-
}
|
|
1132
1032
|
function PayPalPayLaterMessagingPage() {
|
|
1133
1033
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1134
1034
|
}
|
|
@@ -1350,22 +1250,22 @@ const routeModule = {
|
|
|
1350
1250
|
Component: AdditionalSettingsTab,
|
|
1351
1251
|
path: "/settings/paypal/additional-settings"
|
|
1352
1252
|
},
|
|
1353
|
-
{
|
|
1354
|
-
Component: PayPalApplePayPage,
|
|
1355
|
-
path: "/settings/paypal/apple-pay"
|
|
1356
|
-
},
|
|
1357
1253
|
{
|
|
1358
1254
|
Component: AdvancedCardPaymentsTab,
|
|
1359
1255
|
path: "/settings/paypal/advanced-card-payments"
|
|
1360
1256
|
},
|
|
1361
|
-
{
|
|
1362
|
-
Component: PayPalConnectionPage,
|
|
1363
|
-
path: "/settings/paypal/connection"
|
|
1364
|
-
},
|
|
1365
1257
|
{
|
|
1366
1258
|
Component: PayPalGooglePayPage,
|
|
1367
1259
|
path: "/settings/paypal/google-pay"
|
|
1368
1260
|
},
|
|
1261
|
+
{
|
|
1262
|
+
Component: PayPalApplePayPage,
|
|
1263
|
+
path: "/settings/paypal/apple-pay"
|
|
1264
|
+
},
|
|
1265
|
+
{
|
|
1266
|
+
Component: PayPalConnectionPage,
|
|
1267
|
+
path: "/settings/paypal/connection"
|
|
1268
|
+
},
|
|
1369
1269
|
{
|
|
1370
1270
|
Component: PayPalPayLaterMessagingPage,
|
|
1371
1271
|
path: "/settings/paypal/pay-later-messaging"
|