@easypayment/medusa-payment-paypal 0.9.22 → 0.9.24
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 +262 -92
- package/.medusa/server/src/admin/index.mjs +262 -92
- 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 +304 -146
- package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js.map +1 -1
- package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
- package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js +6 -8
- package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js.map +1 -1
- package/.medusa/server/src/api/admin/paypal/environment/route.d.ts.map +1 -1
- package/.medusa/server/src/api/admin/paypal/environment/route.js +11 -3
- package/.medusa/server/src/api/admin/paypal/environment/route.js.map +1 -1
- package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts.map +1 -1
- package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js +4 -1
- package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js.map +1 -1
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +6 -8
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.js +11 -0
- package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.js +2 -4
- package/.medusa/server/src/api/store/paypal-complete/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 +55 -34
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/utils/core-workflow.d.ts +32 -0
- package/.medusa/server/src/modules/paypal/utils/core-workflow.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/core-workflow.js +40 -0
- package/.medusa/server/src/modules/paypal/utils/core-workflow.js.map +1 -0
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/connection/page.tsx +330 -161
- package/src/api/admin/payment-collections/[id]/payment-sessions/route.ts +6 -8
- package/src/api/admin/paypal/environment/route.ts +10 -3
- package/src/api/admin/paypal/onboarding-status/route.ts +4 -1
- package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +6 -8
- package/src/api/store/paypal/capture-order/route.ts +15 -0
- package/src/api/store/paypal-complete/route.ts +6 -4
- package/src/modules/paypal/payment-provider/card-service.ts +72 -38
- package/src/modules/paypal/utils/core-workflow.ts +46 -0
|
@@ -224,6 +224,9 @@ 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
|
+
}
|
|
227
230
|
const DEFAULT_FORM = {
|
|
228
231
|
enabled: true,
|
|
229
232
|
title: "Credit or Debit Card",
|
|
@@ -308,12 +311,6 @@ function AdvancedCardPaymentsTab() {
|
|
|
308
311
|
)
|
|
309
312
|
] }) });
|
|
310
313
|
}
|
|
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
314
|
const config = adminSdk.defineRouteConfig({
|
|
318
315
|
label: "PayPal Connection"
|
|
319
316
|
});
|
|
@@ -363,12 +360,62 @@ function clearCachedUrl(env) {
|
|
|
363
360
|
} catch {
|
|
364
361
|
}
|
|
365
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 ?? 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
|
+
}
|
|
366
413
|
function PayPalConnectionPage() {
|
|
367
414
|
const [env, setEnv] = react.useState("live");
|
|
368
415
|
const [envReady, setEnvReady] = react.useState(false);
|
|
369
416
|
const [connState, setConnState] = react.useState("loading");
|
|
370
|
-
const [partnerReady, setPartnerReady] = react.useState(false);
|
|
371
417
|
const [error, setError] = react.useState(null);
|
|
418
|
+
const [popupBlocked, setPopupBlocked] = react.useState(false);
|
|
372
419
|
const [finalUrl, setFinalUrl] = react.useState("");
|
|
373
420
|
const [showManual, setShowManual] = react.useState(false);
|
|
374
421
|
const [clientId, setClientId] = react.useState("");
|
|
@@ -376,11 +423,20 @@ function PayPalConnectionPage() {
|
|
|
376
423
|
const [statusInfo, setStatusInfo] = react.useState(null);
|
|
377
424
|
const [onboardingInProgress, setOnboardingInProgress] = react.useState(false);
|
|
378
425
|
const initLoaderRef = react.useRef(null);
|
|
426
|
+
const paypalButtonRef = react.useRef(null);
|
|
379
427
|
const errorLogRef = react.useRef(null);
|
|
380
428
|
const runIdRef = react.useRef(0);
|
|
381
429
|
const currentRunId = react.useRef(0);
|
|
382
430
|
const envRef = react.useRef(env);
|
|
383
431
|
envRef.current = env;
|
|
432
|
+
const finalUrlRef = react.useRef(finalUrl);
|
|
433
|
+
finalUrlRef.current = finalUrl;
|
|
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);
|
|
384
440
|
const completedRef = react.useRef(false);
|
|
385
441
|
const ppBtnMeasureRef = react.useRef(null);
|
|
386
442
|
const [ppBtnWidth, setPpBtnWidth] = react.useState(null);
|
|
@@ -391,13 +447,139 @@ function PayPalConnectionPage() {
|
|
|
391
447
|
setConnState("error");
|
|
392
448
|
setError(msg);
|
|
393
449
|
}, []);
|
|
450
|
+
const stopPoll = react.useCallback(() => {
|
|
451
|
+
if (pollRef.current) {
|
|
452
|
+
clearInterval(pollRef.current);
|
|
453
|
+
pollRef.current = null;
|
|
454
|
+
}
|
|
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
|
+
try {
|
|
468
|
+
popup = window.open(url, POPUP_NAME, features);
|
|
469
|
+
} catch {
|
|
470
|
+
popup = null;
|
|
471
|
+
}
|
|
472
|
+
if (popup) {
|
|
473
|
+
popupRef.current = popup;
|
|
474
|
+
try {
|
|
475
|
+
popup.focus();
|
|
476
|
+
} catch {
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return popup;
|
|
480
|
+
}, []);
|
|
481
|
+
const completeOnboarding = react.useCallback(
|
|
482
|
+
async (authCode, sharedId) => {
|
|
483
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
484
|
+
if (!authCode || !sharedId) return;
|
|
485
|
+
if (completedRef.current) return;
|
|
486
|
+
completedRef.current = true;
|
|
487
|
+
stopPoll();
|
|
488
|
+
try {
|
|
489
|
+
window.onbeforeunload = null;
|
|
490
|
+
} catch {
|
|
491
|
+
}
|
|
492
|
+
const activeEnv = envRef.current === "sandbox" ? "sandbox" : "live";
|
|
493
|
+
setOnboardingInProgress(true);
|
|
494
|
+
setConnState("loading");
|
|
495
|
+
setError(null);
|
|
496
|
+
setPopupBlocked(false);
|
|
497
|
+
try {
|
|
498
|
+
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
499
|
+
method: "POST",
|
|
500
|
+
headers: { "content-type": "application/json" },
|
|
501
|
+
credentials: "include",
|
|
502
|
+
body: JSON.stringify({ authCode, sharedId, env: activeEnv })
|
|
503
|
+
});
|
|
504
|
+
if (!res.ok) {
|
|
505
|
+
const txt = await res.text().catch(() => "");
|
|
506
|
+
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
507
|
+
}
|
|
508
|
+
try {
|
|
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
|
+
}
|
|
522
|
+
clearCachedUrl(activeEnv);
|
|
523
|
+
try {
|
|
524
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${activeEnv}`, {
|
|
525
|
+
method: "GET",
|
|
526
|
+
credentials: "include"
|
|
527
|
+
});
|
|
528
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
529
|
+
setStatusInfo(refreshedStatus || null);
|
|
530
|
+
} catch {
|
|
531
|
+
}
|
|
532
|
+
setConnState("connected");
|
|
533
|
+
setShowManual(false);
|
|
534
|
+
} catch (e) {
|
|
535
|
+
completedRef.current = false;
|
|
536
|
+
console.error(e);
|
|
537
|
+
setConnState("error");
|
|
538
|
+
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
539
|
+
} finally {
|
|
540
|
+
setOnboardingInProgress(false);
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
[stopPoll]
|
|
544
|
+
);
|
|
545
|
+
const startStatusPoll = react.useCallback(() => {
|
|
546
|
+
stopPoll();
|
|
547
|
+
let ticks = 0;
|
|
548
|
+
pollRef.current = setInterval(async () => {
|
|
549
|
+
var _a;
|
|
550
|
+
ticks += 1;
|
|
551
|
+
if (completedRef.current || ticks > 150) {
|
|
552
|
+
stopPoll();
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
const r = await fetch(`${STATUS_ENDPOINT}?environment=${envRef.current}`, {
|
|
557
|
+
method: "GET",
|
|
558
|
+
credentials: "include"
|
|
559
|
+
});
|
|
560
|
+
const st = await r.json().catch(() => ({}));
|
|
561
|
+
if ((st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true) {
|
|
562
|
+
completedRef.current = true;
|
|
563
|
+
stopPoll();
|
|
564
|
+
try {
|
|
565
|
+
(_a = popupRef.current) == null ? void 0 : _a.close();
|
|
566
|
+
} catch {
|
|
567
|
+
}
|
|
568
|
+
clearCachedUrl(envRef.current);
|
|
569
|
+
setStatusInfo(st);
|
|
570
|
+
setConnState("connected");
|
|
571
|
+
setShowManual(false);
|
|
572
|
+
setOnboardingInProgress(false);
|
|
573
|
+
}
|
|
574
|
+
} catch {
|
|
575
|
+
}
|
|
576
|
+
}, 2e3);
|
|
577
|
+
}, [stopPoll]);
|
|
394
578
|
const generateLinkAndReload = react.useCallback(
|
|
395
579
|
async (targetEnv, runId) => {
|
|
396
580
|
if (initLoaderRef.current) {
|
|
397
581
|
const loaderText = initLoaderRef.current.querySelector("#loader-text");
|
|
398
|
-
if (loaderText)
|
|
399
|
-
loaderText.textContent = "Generating onboarding session...";
|
|
400
|
-
}
|
|
582
|
+
if (loaderText) loaderText.textContent = "Generating onboarding session...";
|
|
401
583
|
}
|
|
402
584
|
try {
|
|
403
585
|
const res = await fetch(SERVICE_URL, {
|
|
@@ -451,6 +633,7 @@ function PayPalConnectionPage() {
|
|
|
451
633
|
const run = async () => {
|
|
452
634
|
setConnState("loading");
|
|
453
635
|
setError(null);
|
|
636
|
+
setPopupBlocked(false);
|
|
454
637
|
setFinalUrl("");
|
|
455
638
|
try {
|
|
456
639
|
const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
@@ -489,13 +672,6 @@ function PayPalConnectionPage() {
|
|
|
489
672
|
const scriptUrl = PARTNER_JS_URLS[env];
|
|
490
673
|
let cancelled = false;
|
|
491
674
|
let pollTimer;
|
|
492
|
-
setPartnerReady(false);
|
|
493
|
-
const readyFallback = setTimeout(() => {
|
|
494
|
-
if (!cancelled) setPartnerReady(true);
|
|
495
|
-
}, 6e3);
|
|
496
|
-
const markReady = () => {
|
|
497
|
-
if (!cancelled) setPartnerReady(true);
|
|
498
|
-
};
|
|
499
675
|
const initPartner = (attempt = 0) => {
|
|
500
676
|
var _a2, _b2;
|
|
501
677
|
if (cancelled) return;
|
|
@@ -507,7 +683,6 @@ function PayPalConnectionPage() {
|
|
|
507
683
|
} catch (e) {
|
|
508
684
|
console.error("[paypal] partner.js init failed:", e);
|
|
509
685
|
}
|
|
510
|
-
markReady();
|
|
511
686
|
return;
|
|
512
687
|
}
|
|
513
688
|
if (typeof (signup == null ? void 0 : signup.render) === "function") {
|
|
@@ -516,7 +691,6 @@ function PayPalConnectionPage() {
|
|
|
516
691
|
} catch (e) {
|
|
517
692
|
console.error("[paypal] partner.js render failed:", e);
|
|
518
693
|
}
|
|
519
|
-
markReady();
|
|
520
694
|
return;
|
|
521
695
|
}
|
|
522
696
|
if (attempt < 40) {
|
|
@@ -527,7 +701,6 @@ function PayPalConnectionPage() {
|
|
|
527
701
|
document.dispatchEvent(new Event("DOMContentLoaded"));
|
|
528
702
|
} catch {
|
|
529
703
|
}
|
|
530
|
-
markReady();
|
|
531
704
|
};
|
|
532
705
|
const existingScript = document.getElementById("paypal-partner-js");
|
|
533
706
|
if (existingScript) {
|
|
@@ -544,74 +717,39 @@ function PayPalConnectionPage() {
|
|
|
544
717
|
ppScript.src = scriptUrl;
|
|
545
718
|
ppScript.async = true;
|
|
546
719
|
ppScript.onload = () => initPartner();
|
|
547
|
-
ppScript.onerror = () => markReady();
|
|
548
720
|
document.body.appendChild(ppScript);
|
|
549
721
|
return () => {
|
|
550
722
|
cancelled = true;
|
|
551
|
-
clearTimeout(
|
|
552
|
-
if (
|
|
553
|
-
clearTimeout(pollTimer);
|
|
554
|
-
}
|
|
555
|
-
if (ppScript.parentNode) {
|
|
556
|
-
ppScript.parentNode.removeChild(ppScript);
|
|
557
|
-
}
|
|
723
|
+
if (pollTimer) clearTimeout(pollTimer);
|
|
724
|
+
if (ppScript.parentNode) ppScript.parentNode.removeChild(ppScript);
|
|
558
725
|
};
|
|
559
726
|
}, [connState, finalUrl, env]);
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
if (completedRef.current) return;
|
|
564
|
-
completedRef.current = true;
|
|
565
|
-
try {
|
|
566
|
-
window.onbeforeunload = null;
|
|
567
|
-
} catch {
|
|
568
|
-
}
|
|
569
|
-
const activeEnv = envRef.current === "sandbox" ? "sandbox" : "live";
|
|
570
|
-
setOnboardingInProgress(true);
|
|
571
|
-
setConnState("loading");
|
|
572
|
-
setError(null);
|
|
573
|
-
try {
|
|
574
|
-
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
575
|
-
method: "POST",
|
|
576
|
-
headers: { "content-type": "application/json" },
|
|
577
|
-
credentials: "include",
|
|
578
|
-
body: JSON.stringify({ authCode, sharedId, env: activeEnv })
|
|
579
|
-
});
|
|
580
|
-
if (!res.ok) {
|
|
581
|
-
const txt = await res.text().catch(() => "");
|
|
582
|
-
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
583
|
-
}
|
|
727
|
+
react.useEffect(() => {
|
|
728
|
+
const onMessage = (ev) => {
|
|
729
|
+
let serialized = "";
|
|
584
730
|
try {
|
|
585
|
-
|
|
586
|
-
if (typeof close1 === "function") close1();
|
|
731
|
+
serialized = typeof ev.data === "string" ? ev.data : JSON.stringify(ev.data);
|
|
587
732
|
} catch {
|
|
733
|
+
serialized = String(ev.data);
|
|
588
734
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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
|
+
);
|
|
593
743
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
credentials: "include"
|
|
599
|
-
});
|
|
600
|
-
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
601
|
-
setStatusInfo(refreshedStatus || null);
|
|
602
|
-
} catch {
|
|
744
|
+
if (!isPayPalOrigin(ev.origin)) return;
|
|
745
|
+
const { authCode, sharedId } = extractAuth(ev.data);
|
|
746
|
+
if (authCode && sharedId) {
|
|
747
|
+
completeOnboarding(authCode, sharedId);
|
|
603
748
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
console.error(e);
|
|
609
|
-
setConnState("error");
|
|
610
|
-
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
611
|
-
} finally {
|
|
612
|
-
setOnboardingInProgress(false);
|
|
613
|
-
}
|
|
614
|
-
}, []);
|
|
749
|
+
};
|
|
750
|
+
window.addEventListener("message", onMessage);
|
|
751
|
+
return () => window.removeEventListener("message", onMessage);
|
|
752
|
+
}, [completeOnboarding]);
|
|
615
753
|
react.useLayoutEffect(() => {
|
|
616
754
|
window.onboardingCallback = (authCode, sharedId) => {
|
|
617
755
|
completeOnboarding(authCode, sharedId);
|
|
@@ -620,6 +758,32 @@ function PayPalConnectionPage() {
|
|
|
620
758
|
window.onboardingCallback = void 0;
|
|
621
759
|
};
|
|
622
760
|
}, [completeOnboarding]);
|
|
761
|
+
react.useEffect(() => {
|
|
762
|
+
const onCaptureClick = (e) => {
|
|
763
|
+
const btn = paypalButtonRef.current;
|
|
764
|
+
if (!btn) return;
|
|
765
|
+
const target = e.target;
|
|
766
|
+
if (!target || !btn.contains(target)) return;
|
|
767
|
+
e.preventDefault();
|
|
768
|
+
e.stopImmediatePropagation();
|
|
769
|
+
if (connStateRef.current !== "ready" || !finalUrlRef.current || inProgressRef.current) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
completedRef.current = false;
|
|
773
|
+
const popup = openOnboardingPopup(finalUrlRef.current);
|
|
774
|
+
if (!popup) {
|
|
775
|
+
setPopupBlocked(true);
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
setPopupBlocked(false);
|
|
779
|
+
startStatusPoll();
|
|
780
|
+
};
|
|
781
|
+
document.addEventListener("click", onCaptureClick, true);
|
|
782
|
+
return () => document.removeEventListener("click", onCaptureClick, true);
|
|
783
|
+
}, [openOnboardingPopup, startStatusPoll]);
|
|
784
|
+
react.useEffect(() => {
|
|
785
|
+
return () => stopPoll();
|
|
786
|
+
}, [stopPoll]);
|
|
623
787
|
react.useLayoutEffect(() => {
|
|
624
788
|
const el = ppBtnMeasureRef.current;
|
|
625
789
|
if (!el) return;
|
|
@@ -640,6 +804,9 @@ function PayPalConnectionPage() {
|
|
|
640
804
|
else window.removeEventListener("resize", update);
|
|
641
805
|
};
|
|
642
806
|
}, [connState, env, finalUrl]);
|
|
807
|
+
const handleConnectClick = (e) => {
|
|
808
|
+
e.preventDefault();
|
|
809
|
+
};
|
|
643
810
|
const handleSaveManual = async () => {
|
|
644
811
|
if (!canSaveManual || onboardingInProgress) return;
|
|
645
812
|
setOnboardingInProgress(true);
|
|
@@ -714,6 +881,7 @@ function PayPalConnectionPage() {
|
|
|
714
881
|
if (next === env || onboardingInProgress) return;
|
|
715
882
|
completedRef.current = false;
|
|
716
883
|
clearCachedUrl();
|
|
884
|
+
setPopupBlocked(false);
|
|
717
885
|
setConnState("loading");
|
|
718
886
|
try {
|
|
719
887
|
await fetch(ENVIRONMENT_ENDPOINT, {
|
|
@@ -784,6 +952,7 @@ function PayPalConnectionPage() {
|
|
|
784
952
|
"a",
|
|
785
953
|
{
|
|
786
954
|
ref: (node) => {
|
|
955
|
+
paypalButtonRef.current = node;
|
|
787
956
|
ppBtnMeasureRef.current = node;
|
|
788
957
|
},
|
|
789
958
|
id: "paypal-button",
|
|
@@ -791,19 +960,17 @@ function PayPalConnectionPage() {
|
|
|
791
960
|
"data-paypal-button": "true",
|
|
792
961
|
href: finalUrl || "#",
|
|
793
962
|
"data-paypal-onboard-complete": "onboardingCallback",
|
|
794
|
-
|
|
963
|
+
onClick: handleConnectClick,
|
|
795
964
|
className: "transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none no-underline shadow-buttons-neutral text-ui-fg-base bg-ui-button-neutral after:transition-fg after:absolute after:inset-0 after:content-[''] after:button-neutral-gradient hover:bg-ui-button-neutral-hover hover:after:button-neutral-hover-gradient active:bg-ui-button-neutral-pressed active:after:button-neutral-pressed-gradient focus-visible:shadow-buttons-neutral-focus disabled:bg-ui-bg-disabled disabled:border-ui-border-base disabled:text-ui-fg-disabled disabled:shadow-buttons-neutral disabled:after:hidden txt-compact-small-plus px-3 py-1.5",
|
|
796
965
|
style: {
|
|
797
|
-
cursor: onboardingInProgress
|
|
798
|
-
opacity: onboardingInProgress
|
|
799
|
-
|
|
800
|
-
// but un-clickable until partner.js has taken over the
|
|
801
|
-
// click — so it can never open a tab via the native href.
|
|
802
|
-
pointerEvents: onboardingInProgress || !partnerReady ? "none" : "auto"
|
|
966
|
+
cursor: onboardingInProgress ? "not-allowed" : "pointer",
|
|
967
|
+
opacity: onboardingInProgress ? 0.6 : 1,
|
|
968
|
+
pointerEvents: onboardingInProgress ? "none" : "auto"
|
|
803
969
|
},
|
|
804
|
-
children:
|
|
970
|
+
children: "Connect to PayPal"
|
|
805
971
|
}
|
|
806
972
|
),
|
|
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." }),
|
|
807
974
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
808
975
|
"div",
|
|
809
976
|
{
|
|
@@ -959,6 +1126,9 @@ function PayPalConnectionPage() {
|
|
|
959
1126
|
` })
|
|
960
1127
|
] });
|
|
961
1128
|
}
|
|
1129
|
+
function PayPalGooglePayPage() {
|
|
1130
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1131
|
+
}
|
|
962
1132
|
function PayPalPayLaterMessagingPage() {
|
|
963
1133
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
964
1134
|
}
|
|
@@ -1180,22 +1350,22 @@ const routeModule = {
|
|
|
1180
1350
|
Component: AdditionalSettingsTab,
|
|
1181
1351
|
path: "/settings/paypal/additional-settings"
|
|
1182
1352
|
},
|
|
1183
|
-
{
|
|
1184
|
-
Component: AdvancedCardPaymentsTab,
|
|
1185
|
-
path: "/settings/paypal/advanced-card-payments"
|
|
1186
|
-
},
|
|
1187
1353
|
{
|
|
1188
1354
|
Component: PayPalApplePayPage,
|
|
1189
1355
|
path: "/settings/paypal/apple-pay"
|
|
1190
1356
|
},
|
|
1191
1357
|
{
|
|
1192
|
-
Component:
|
|
1193
|
-
path: "/settings/paypal/
|
|
1358
|
+
Component: AdvancedCardPaymentsTab,
|
|
1359
|
+
path: "/settings/paypal/advanced-card-payments"
|
|
1194
1360
|
},
|
|
1195
1361
|
{
|
|
1196
1362
|
Component: PayPalConnectionPage,
|
|
1197
1363
|
path: "/settings/paypal/connection"
|
|
1198
1364
|
},
|
|
1365
|
+
{
|
|
1366
|
+
Component: PayPalGooglePayPage,
|
|
1367
|
+
path: "/settings/paypal/google-pay"
|
|
1368
|
+
},
|
|
1199
1369
|
{
|
|
1200
1370
|
Component: PayPalPayLaterMessagingPage,
|
|
1201
1371
|
path: "/settings/paypal/pay-later-messaging"
|