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