@easypayment/medusa-payment-paypal 0.9.21 → 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.
Files changed (40) hide show
  1. package/.medusa/server/src/admin/index.js +258 -214
  2. package/.medusa/server/src/admin/index.mjs +258 -214
  3. package/.medusa/server/src/admin/routes/settings/paypal/connection/page.d.ts.map +1 -1
  4. package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js +210 -223
  5. package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js.map +1 -1
  6. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
  7. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js +6 -8
  8. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js.map +1 -1
  9. package/.medusa/server/src/api/admin/paypal/environment/route.d.ts.map +1 -1
  10. package/.medusa/server/src/api/admin/paypal/environment/route.js +11 -3
  11. package/.medusa/server/src/api/admin/paypal/environment/route.js.map +1 -1
  12. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts.map +1 -1
  13. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js +4 -1
  14. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js.map +1 -1
  15. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
  16. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +6 -8
  17. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
  18. package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
  19. package/.medusa/server/src/api/store/paypal/capture-order/route.js +11 -0
  20. package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
  21. package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
  22. package/.medusa/server/src/api/store/paypal-complete/route.js +2 -4
  23. package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -1
  24. package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts.map +1 -1
  25. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js +55 -34
  26. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -1
  27. package/.medusa/server/src/modules/paypal/utils/core-workflow.d.ts +32 -0
  28. package/.medusa/server/src/modules/paypal/utils/core-workflow.d.ts.map +1 -0
  29. package/.medusa/server/src/modules/paypal/utils/core-workflow.js +40 -0
  30. package/.medusa/server/src/modules/paypal/utils/core-workflow.js.map +1 -0
  31. package/package.json +1 -1
  32. package/src/admin/routes/settings/paypal/connection/page.tsx +273 -293
  33. package/src/api/admin/payment-collections/[id]/payment-sessions/route.ts +6 -8
  34. package/src/api/admin/paypal/environment/route.ts +10 -3
  35. package/src/api/admin/paypal/onboarding-status/route.ts +4 -1
  36. package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +6 -8
  37. package/src/api/store/paypal/capture-order/route.ts +15 -0
  38. package/src/api/store/paypal-complete/route.ts +6 -4
  39. package/src/modules/paypal/payment-provider/card-service.ts +72 -38
  40. package/src/modules/paypal/utils/core-workflow.ts +46 -0
@@ -134,22 +134,20 @@ async function adminFetch(path, opts = {}) {
134
134
  }
135
135
  }
136
136
  const DEFAULT_FORM$1 = {
137
- enabled: true,
138
- title: "Credit or Debit Card",
139
- threeDS: "when_required"
137
+ paymentAction: "capture",
138
+ brandName: "PayPal",
139
+ landingPage: "no_preference",
140
+ requireInstantPayment: false,
141
+ sendItemDetails: true,
142
+ invoicePrefix: "PP-",
143
+ creditCardStatementName: "PayPal"
140
144
  };
141
145
  function mergeWithDefaults$1(saved) {
142
146
  if (!saved) return { ...DEFAULT_FORM$1 };
143
147
  const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
144
148
  return { ...DEFAULT_FORM$1, ...Object.fromEntries(entries) };
145
149
  }
146
- const THREE_DS_OPTIONS = [
147
- { value: "when_required", label: "3D Secure when required", hint: "Triggers 3DS only when the card / issuer requires it." },
148
- { value: "sli", label: "3D Secure (SCA) / liability shift (recommended)", hint: "Attempts to optimize for liability shift while remaining compliant." },
149
- { value: "always", label: "Always request 3D Secure", hint: "Forces 3DS challenge whenever possible (may reduce conversion)." }
150
- ];
151
- function AdvancedCardPaymentsTab() {
152
- var _a, _b;
150
+ function AdditionalSettingsTab() {
153
151
  const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM$1 }));
154
152
  const [loading, setLoading] = react.useState(false);
155
153
  const [saving, setSaving] = react.useState(false);
@@ -164,7 +162,7 @@ function AdvancedCardPaymentsTab() {
164
162
  setLoading(true);
165
163
  const json = await adminFetch("/admin/paypal/settings");
166
164
  const payload = (json == null ? void 0 : json.data) ?? json;
167
- const saved = payload == null ? void 0 : payload.advanced_card_payments;
165
+ const saved = payload == null ? void 0 : payload.additional_settings;
168
166
  if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
169
167
  } catch {
170
168
  } finally {
@@ -175,16 +173,14 @@ function AdvancedCardPaymentsTab() {
175
173
  async function onSave() {
176
174
  try {
177
175
  setSaving(true);
178
- const json = await adminFetch("/admin/paypal/settings", {
179
- method: "POST",
180
- body: { advanced_card_payments: form }
181
- });
176
+ setToast(null);
177
+ const json = await adminFetch("/admin/paypal/settings", { method: "POST", body: { additional_settings: form } });
182
178
  const payload = (json == null ? void 0 : json.data) ?? json;
183
- const saved = payload == null ? void 0 : payload.advanced_card_payments;
179
+ const saved = payload == null ? void 0 : payload.additional_settings;
184
180
  if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
185
181
  setToast({ kind: "success", message: "Settings saved" });
186
182
  } catch (e) {
187
- setToast({ kind: "error", message: (e instanceof Error ? e.message : "") || "Failed to save settings." });
183
+ setToast({ kind: "error", message: e instanceof Error ? e.message : "Failed to save settings" });
188
184
  } finally {
189
185
  setSaving(false);
190
186
  }
@@ -196,42 +192,58 @@ function AdvancedCardPaymentsTab() {
196
192
  /* @__PURE__ */ jsxRuntime.jsx(
197
193
  SectionCard,
198
194
  {
199
- title: "Advanced Card Payments",
200
- description: "Control card checkout settings and 3D Secure behavior.",
195
+ title: "Additional Settings",
196
+ description: "These settings control checkout behavior and PayPal experience.",
201
197
  right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
202
198
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none 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", children: saving ? "Saving..." : "Save settings" }),
203
199
  loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
204
200
  ] }),
205
201
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
206
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Enable/Disable", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
207
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.enabled, onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
208
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
202
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Payment action", htmlFor: "as-payment-action", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-payment-action", value: form.paymentAction, onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
203
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
204
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
209
205
  ] }) }),
210
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Title", htmlFor: "acp-title", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "acp-title", value: form.title, onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "Credit or Debit Card" }) }),
211
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Contingency for 3D Secure", hint: "Choose when 3D Secure should be triggered during card payments.", htmlFor: "acp-threeds", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
212
- /* @__PURE__ */ jsxRuntime.jsx("select", { id: "acp-threeds", value: form.threeDS, onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value)) }),
213
- ((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: (_b = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _b.hint }) : null
214
- ] }) })
206
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Brand Name", htmlFor: "as-brand-name", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-brand-name", value: form.brandName, onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
207
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Landing Page", htmlFor: "as-landing-page", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-landing-page", value: form.landingPage, onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
208
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
209
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
210
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
211
+ ] }) }),
212
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
213
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.requireInstantPayment, onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
214
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
215
+ ] }) }),
216
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Send Item Details", hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
217
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.sendItemDetails, onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
218
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
219
+ ] }) }),
220
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Invoice prefix", htmlFor: "as-invoice-prefix", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-invoice-prefix", value: form.invoicePrefix, onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PP-" }) }),
221
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Credit Card Statement Name", htmlFor: "as-cc-statement", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-cc-statement", value: form.creditCardStatementName, onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) })
215
222
  ] })
216
223
  }
217
224
  )
218
225
  ] }) });
219
226
  }
227
+ function PayPalApplePayPage() {
228
+ return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
229
+ }
220
230
  const DEFAULT_FORM = {
221
- paymentAction: "capture",
222
- brandName: "PayPal",
223
- landingPage: "no_preference",
224
- requireInstantPayment: false,
225
- sendItemDetails: true,
226
- invoicePrefix: "PP-",
227
- creditCardStatementName: "PayPal"
231
+ enabled: true,
232
+ title: "Credit or Debit Card",
233
+ threeDS: "when_required"
228
234
  };
229
235
  function mergeWithDefaults(saved) {
230
236
  if (!saved) return { ...DEFAULT_FORM };
231
237
  const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
232
238
  return { ...DEFAULT_FORM, ...Object.fromEntries(entries) };
233
239
  }
234
- function AdditionalSettingsTab() {
240
+ const THREE_DS_OPTIONS = [
241
+ { value: "when_required", label: "3D Secure when required", hint: "Triggers 3DS only when the card / issuer requires it." },
242
+ { value: "sli", label: "3D Secure (SCA) / liability shift (recommended)", hint: "Attempts to optimize for liability shift while remaining compliant." },
243
+ { value: "always", label: "Always request 3D Secure", hint: "Forces 3DS challenge whenever possible (may reduce conversion)." }
244
+ ];
245
+ function AdvancedCardPaymentsTab() {
246
+ var _a, _b;
235
247
  const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM }));
236
248
  const [loading, setLoading] = react.useState(false);
237
249
  const [saving, setSaving] = react.useState(false);
@@ -246,7 +258,7 @@ function AdditionalSettingsTab() {
246
258
  setLoading(true);
247
259
  const json = await adminFetch("/admin/paypal/settings");
248
260
  const payload = (json == null ? void 0 : json.data) ?? json;
249
- const saved = payload == null ? void 0 : payload.additional_settings;
261
+ const saved = payload == null ? void 0 : payload.advanced_card_payments;
250
262
  if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
251
263
  } catch {
252
264
  } finally {
@@ -257,14 +269,16 @@ function AdditionalSettingsTab() {
257
269
  async function onSave() {
258
270
  try {
259
271
  setSaving(true);
260
- setToast(null);
261
- const json = await adminFetch("/admin/paypal/settings", { method: "POST", body: { additional_settings: form } });
272
+ const json = await adminFetch("/admin/paypal/settings", {
273
+ method: "POST",
274
+ body: { advanced_card_payments: form }
275
+ });
262
276
  const payload = (json == null ? void 0 : json.data) ?? json;
263
- const saved = payload == null ? void 0 : payload.additional_settings;
277
+ const saved = payload == null ? void 0 : payload.advanced_card_payments;
264
278
  if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
265
279
  setToast({ kind: "success", message: "Settings saved" });
266
280
  } catch (e) {
267
- setToast({ kind: "error", message: e instanceof Error ? e.message : "Failed to save settings" });
281
+ setToast({ kind: "error", message: (e instanceof Error ? e.message : "") || "Failed to save settings." });
268
282
  } finally {
269
283
  setSaving(false);
270
284
  }
@@ -276,44 +290,27 @@ function AdditionalSettingsTab() {
276
290
  /* @__PURE__ */ jsxRuntime.jsx(
277
291
  SectionCard,
278
292
  {
279
- title: "Additional Settings",
280
- description: "These settings control checkout behavior and PayPal experience.",
293
+ title: "Advanced Card Payments",
294
+ description: "Control card checkout settings and 3D Secure behavior.",
281
295
  right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
282
296
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none 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", children: saving ? "Saving..." : "Save settings" }),
283
297
  loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
284
298
  ] }),
285
299
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
286
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Payment action", htmlFor: "as-payment-action", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-payment-action", value: form.paymentAction, onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
287
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
288
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
289
- ] }) }),
290
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Brand Name", htmlFor: "as-brand-name", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-brand-name", value: form.brandName, onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
291
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Landing Page", htmlFor: "as-landing-page", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-landing-page", value: form.landingPage, onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
292
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
293
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
294
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
295
- ] }) }),
296
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
297
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.requireInstantPayment, onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
298
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
299
- ] }) }),
300
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Send Item Details", hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
301
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.sendItemDetails, onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
302
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
300
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Enable/Disable", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
301
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.enabled, onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
302
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
303
303
  ] }) }),
304
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Invoice prefix", htmlFor: "as-invoice-prefix", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-invoice-prefix", value: form.invoicePrefix, onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PP-" }) }),
305
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Credit Card Statement Name", htmlFor: "as-cc-statement", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-cc-statement", value: form.creditCardStatementName, onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) })
304
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Title", htmlFor: "acp-title", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "acp-title", value: form.title, onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "Credit or Debit Card" }) }),
305
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Contingency for 3D Secure", hint: "Choose when 3D Secure should be triggered during card payments.", htmlFor: "acp-threeds", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
306
+ /* @__PURE__ */ jsxRuntime.jsx("select", { id: "acp-threeds", value: form.threeDS, onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value)) }),
307
+ ((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: (_b = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _b.hint }) : null
308
+ ] }) })
306
309
  ] })
307
310
  }
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
  });
@@ -324,7 +321,7 @@ const PARTNER_JS_URLS = {
324
321
  const SERVICE_URL = "/admin/paypal/onboarding-link";
325
322
  const POPUP_NAME = "PPFrame";
326
323
  const CACHE_PREFIX = "pp_onboard_cache";
327
- const CACHE_EXPIRY = 10 * 60 * 1e3;
324
+ const CACHE_EXPIRY = 6 * 60 * 60 * 1e3;
328
325
  const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
329
326
  const STATUS_ENDPOINT = "/admin/paypal/status";
330
327
  const SAVE_CREDENTIALS_ENDPOINT = "/admin/paypal/save-credentials";
@@ -347,7 +344,9 @@ function readCachedUrl(env) {
347
344
  function writeCachedUrl(env, url) {
348
345
  try {
349
346
  localStorage.setItem(cacheKeyFor(env), JSON.stringify({ url, ts: Date.now() }));
347
+ return readCachedUrl(env) === url;
350
348
  } catch {
349
+ return false;
351
350
  }
352
351
  }
353
352
  function clearCachedUrl(env) {
@@ -373,23 +372,27 @@ function extractAuth(data) {
373
372
  if (!data) return {};
374
373
  if (typeof data === "object") {
375
374
  const obj = data;
376
- const authCode = obj.authCode ?? obj.auth_code ?? obj.authcode;
375
+ const authCode = obj.authCode ?? obj.auth_code ?? obj.authcode ?? obj.code;
377
376
  const sharedId = obj.sharedId ?? obj.shared_id ?? obj.sharedid;
378
377
  if (authCode && sharedId) {
379
378
  return { authCode: String(authCode), sharedId: String(sharedId) };
380
379
  }
381
- for (const key of ["data", "payload", "message", "detail", "body"]) {
380
+ for (const key of ["data", "payload", "message", "detail", "body", "params"]) {
382
381
  if (obj[key] && typeof obj[key] === "object") {
383
382
  const inner = extractAuth(obj[key]);
384
383
  if (inner.authCode && inner.sharedId) return inner;
385
384
  }
385
+ if (typeof obj[key] === "string") {
386
+ const inner = extractAuth(obj[key]);
387
+ if (inner.authCode && inner.sharedId) return inner;
388
+ }
386
389
  }
387
390
  return {};
388
391
  }
389
392
  if (typeof data === "string") {
390
393
  const s = data.trim();
391
394
  if (!s) return {};
392
- if (s.startsWith("{")) {
395
+ if (s.startsWith("{") || s.startsWith("[")) {
393
396
  try {
394
397
  return extractAuth(JSON.parse(s));
395
398
  } catch {
@@ -424,16 +427,16 @@ function PayPalConnectionPage() {
424
427
  const errorLogRef = react.useRef(null);
425
428
  const runIdRef = react.useRef(0);
426
429
  const currentRunId = react.useRef(0);
430
+ const envRef = react.useRef(env);
431
+ envRef.current = env;
427
432
  const finalUrlRef = react.useRef(finalUrl);
428
433
  finalUrlRef.current = finalUrl;
429
434
  const connStateRef = react.useRef(connState);
430
435
  connStateRef.current = connState;
431
436
  const inProgressRef = react.useRef(onboardingInProgress);
432
437
  inProgressRef.current = onboardingInProgress;
433
- const envRef = react.useRef(env);
434
- envRef.current = env;
435
438
  const popupRef = react.useRef(null);
436
- const popupPollRef = react.useRef(null);
439
+ const pollRef = react.useRef(null);
437
440
  const completedRef = react.useRef(false);
438
441
  const ppBtnMeasureRef = react.useRef(null);
439
442
  const [ppBtnWidth, setPpBtnWidth] = react.useState(null);
@@ -444,52 +447,44 @@ function PayPalConnectionPage() {
444
447
  setConnState("error");
445
448
  setError(msg);
446
449
  }, []);
447
- const stopPopupPoll = react.useCallback(() => {
448
- if (popupPollRef.current) {
449
- clearInterval(popupPollRef.current);
450
- popupPollRef.current = null;
450
+ const stopPoll = react.useCallback(() => {
451
+ if (pollRef.current) {
452
+ clearInterval(pollRef.current);
453
+ pollRef.current = null;
451
454
  }
452
455
  }, []);
453
- const openOnboardingPopup = react.useCallback(
454
- (url) => {
455
- const w = 450;
456
- const h = 600;
457
- const baseLeft = typeof window.screenX === "number" ? window.screenX : window.screenLeft || 0;
458
- const baseTop = typeof window.screenY === "number" ? window.screenY : window.screenTop || 0;
459
- const outerW = window.outerWidth || document.documentElement.clientWidth || 1024;
460
- const outerH = window.outerHeight || document.documentElement.clientHeight || 768;
461
- const left = Math.round(baseLeft + Math.max(0, (outerW - w) / 2));
462
- const top = Math.round(baseTop + Math.max(0, (outerH - h) / 2));
463
- const features = `popup=yes,width=${w},height=${h},left=${left},top=${top},scrollbars=yes,resizable=yes`;
464
- let popup = null;
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;
465
474
  try {
466
- popup = window.open(url, POPUP_NAME, features);
475
+ popup.focus();
467
476
  } catch {
468
- popup = null;
469
- }
470
- if (popup) {
471
- popupRef.current = popup;
472
- try {
473
- popup.focus();
474
- } catch {
475
- }
476
- stopPopupPoll();
477
- popupPollRef.current = setInterval(() => {
478
- if (!popupRef.current || popupRef.current.closed) {
479
- stopPopupPoll();
480
- }
481
- }, 1e3);
482
477
  }
483
- return popup;
484
- },
485
- [stopPopupPoll]
486
- );
478
+ }
479
+ return popup;
480
+ }, []);
487
481
  const completeOnboarding = react.useCallback(
488
482
  async (authCode, sharedId) => {
489
483
  var _a, _b, _c, _d, _e, _f, _g, _h;
490
484
  if (!authCode || !sharedId) return;
491
485
  if (completedRef.current) return;
492
486
  completedRef.current = true;
487
+ stopPoll();
493
488
  try {
494
489
  window.onbeforeunload = null;
495
490
  } catch {
@@ -514,7 +509,6 @@ function PayPalConnectionPage() {
514
509
  (_a = popupRef.current) == null ? void 0 : _a.close();
515
510
  } catch {
516
511
  }
517
- stopPopupPoll();
518
512
  try {
519
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;
520
514
  if (typeof close1 === "function") close1();
@@ -527,10 +521,10 @@ function PayPalConnectionPage() {
527
521
  }
528
522
  clearCachedUrl(activeEnv);
529
523
  try {
530
- const statusRes = await fetch(
531
- `${STATUS_ENDPOINT}?environment=${activeEnv}`,
532
- { method: "GET", credentials: "include" }
533
- );
524
+ const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${activeEnv}`, {
525
+ method: "GET",
526
+ credentials: "include"
527
+ });
534
528
  const refreshedStatus = await statusRes.json().catch(() => ({}));
535
529
  setStatusInfo(refreshedStatus || null);
536
530
  } catch {
@@ -546,29 +540,56 @@ function PayPalConnectionPage() {
546
540
  setOnboardingInProgress(false);
547
541
  }
548
542
  },
549
- [stopPopupPoll]
543
+ [stopPoll]
550
544
  );
551
- const fetchFreshLink = react.useCallback(
552
- (runId, targetEnv) => {
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]);
578
+ const generateLinkAndReload = react.useCallback(
579
+ async (targetEnv, runId) => {
553
580
  if (initLoaderRef.current) {
554
581
  const loaderText = initLoaderRef.current.querySelector("#loader-text");
555
- if (loaderText)
556
- loaderText.textContent = "Generating onboarding session...";
582
+ if (loaderText) loaderText.textContent = "Generating onboarding session...";
557
583
  }
558
- fetch(SERVICE_URL, {
559
- method: "POST",
560
- headers: { "content-type": "application/json" },
561
- credentials: "include",
562
- body: JSON.stringify({
563
- products: ["PPCP"],
564
- // Generate the link for the explicitly selected environment so it can
565
- // never depend on a racing POST /environment having landed yet.
566
- environment: targetEnv
567
- })
568
- }).then((r) => {
569
- if (!r.ok) throw new Error(`Service returned ${r.status}`);
570
- return r.json();
571
- }).then((data) => {
584
+ try {
585
+ const res = await fetch(SERVICE_URL, {
586
+ method: "POST",
587
+ headers: { "content-type": "application/json" },
588
+ credentials: "include",
589
+ body: JSON.stringify({ products: ["PPCP"], environment: targetEnv })
590
+ });
591
+ if (!res.ok) throw new Error(`Service returned ${res.status}`);
592
+ const data = await res.json();
572
593
  if (runId !== currentRunId.current) return;
573
594
  const href = data == null ? void 0 : data.onboarding_url;
574
595
  if (!href) {
@@ -576,13 +597,17 @@ function PayPalConnectionPage() {
576
597
  return;
577
598
  }
578
599
  const url = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
579
- writeCachedUrl(targetEnv, url);
600
+ const persisted = writeCachedUrl(targetEnv, url);
601
+ if (persisted) {
602
+ window.location.reload();
603
+ return;
604
+ }
580
605
  setFinalUrl(url);
581
606
  setConnState("ready");
582
- }).catch(() => {
607
+ } catch {
583
608
  if (runId !== currentRunId.current) return;
584
609
  showError("Unable to connect to service.");
585
- });
610
+ }
586
611
  },
587
612
  [showError]
588
613
  );
@@ -599,6 +624,48 @@ function PayPalConnectionPage() {
599
624
  alive = false;
600
625
  };
601
626
  }, []);
627
+ react.useEffect(() => {
628
+ if (!envReady) return;
629
+ currentRunId.current = ++runIdRef.current;
630
+ const runId = currentRunId.current;
631
+ let cancelled = false;
632
+ completedRef.current = false;
633
+ const run = async () => {
634
+ setConnState("loading");
635
+ setError(null);
636
+ setPopupBlocked(false);
637
+ setFinalUrl("");
638
+ try {
639
+ const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
640
+ method: "GET",
641
+ credentials: "include"
642
+ });
643
+ const st = await r.json().catch(() => ({}));
644
+ if (cancelled || runId !== currentRunId.current) return;
645
+ setStatusInfo(st);
646
+ const isConnected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
647
+ if (isConnected) {
648
+ setConnState("connected");
649
+ setShowManual(false);
650
+ return;
651
+ }
652
+ } catch (e) {
653
+ console.error(e);
654
+ }
655
+ if (cancelled || runId !== currentRunId.current) return;
656
+ const cached = readCachedUrl(env);
657
+ if (cached) {
658
+ setFinalUrl(cached);
659
+ setConnState("ready");
660
+ return;
661
+ }
662
+ await generateLinkAndReload(env, runId);
663
+ };
664
+ run();
665
+ return () => {
666
+ cancelled = true;
667
+ };
668
+ }, [env, envReady, generateLinkAndReload]);
602
669
  react.useEffect(() => {
603
670
  var _a, _b, _c;
604
671
  if (connState !== "ready" || !finalUrl) return;
@@ -653,16 +720,27 @@ function PayPalConnectionPage() {
653
720
  document.body.appendChild(ppScript);
654
721
  return () => {
655
722
  cancelled = true;
656
- if (pollTimer) {
657
- clearTimeout(pollTimer);
658
- }
659
- if (ppScript.parentNode) {
660
- ppScript.parentNode.removeChild(ppScript);
661
- }
723
+ if (pollTimer) clearTimeout(pollTimer);
724
+ if (ppScript.parentNode) ppScript.parentNode.removeChild(ppScript);
662
725
  };
663
726
  }, [connState, finalUrl, env]);
664
727
  react.useEffect(() => {
665
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
+ }
666
744
  if (!isPayPalOrigin(ev.origin)) return;
667
745
  const { authCode, sharedId } = extractAuth(ev.data);
668
746
  if (authCode && sharedId) {
@@ -672,48 +750,6 @@ function PayPalConnectionPage() {
672
750
  window.addEventListener("message", onMessage);
673
751
  return () => window.removeEventListener("message", onMessage);
674
752
  }, [completeOnboarding]);
675
- react.useEffect(() => {
676
- if (!envReady) return;
677
- currentRunId.current = ++runIdRef.current;
678
- const runId = currentRunId.current;
679
- let cancelled = false;
680
- completedRef.current = false;
681
- const run = async () => {
682
- setConnState("loading");
683
- setError(null);
684
- setPopupBlocked(false);
685
- setFinalUrl("");
686
- try {
687
- const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
688
- method: "GET",
689
- credentials: "include"
690
- });
691
- const st = await r.json().catch(() => ({}));
692
- if (cancelled || runId !== currentRunId.current) return;
693
- setStatusInfo(st);
694
- const isConnected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
695
- if (isConnected) {
696
- setConnState("connected");
697
- setShowManual(false);
698
- return;
699
- }
700
- } catch (e) {
701
- console.error(e);
702
- }
703
- if (cancelled || runId !== currentRunId.current) return;
704
- const cached = readCachedUrl(env);
705
- if (cached) {
706
- setFinalUrl(cached);
707
- setConnState("ready");
708
- } else {
709
- fetchFreshLink(runId, env);
710
- }
711
- };
712
- run();
713
- return () => {
714
- cancelled = true;
715
- };
716
- }, [env, envReady, fetchFreshLink]);
717
753
  react.useLayoutEffect(() => {
718
754
  window.onboardingCallback = (authCode, sharedId) => {
719
755
  completeOnboarding(authCode, sharedId);
@@ -723,10 +759,31 @@ function PayPalConnectionPage() {
723
759
  };
724
760
  }, [completeOnboarding]);
725
761
  react.useEffect(() => {
726
- return () => {
727
- stopPopupPoll();
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();
728
780
  };
729
- }, [stopPopupPoll]);
781
+ document.addEventListener("click", onCaptureClick, true);
782
+ return () => document.removeEventListener("click", onCaptureClick, true);
783
+ }, [openOnboardingPopup, startStatusPoll]);
784
+ react.useEffect(() => {
785
+ return () => stopPoll();
786
+ }, [stopPoll]);
730
787
  react.useLayoutEffect(() => {
731
788
  const el = ppBtnMeasureRef.current;
732
789
  if (!el) return;
@@ -747,23 +804,6 @@ function PayPalConnectionPage() {
747
804
  else window.removeEventListener("resize", update);
748
805
  };
749
806
  }, [connState, env, finalUrl]);
750
- react.useEffect(() => {
751
- const onCaptureClick = (e) => {
752
- const btn = paypalButtonRef.current;
753
- if (!btn) return;
754
- const target = e.target;
755
- if (!target || !btn.contains(target)) return;
756
- e.preventDefault();
757
- if (connStateRef.current !== "ready" || !finalUrlRef.current || inProgressRef.current) {
758
- return;
759
- }
760
- completedRef.current = false;
761
- const popup = openOnboardingPopup(finalUrlRef.current);
762
- setPopupBlocked(!popup);
763
- };
764
- document.addEventListener("click", onCaptureClick, true);
765
- return () => document.removeEventListener("click", onCaptureClick, true);
766
- }, [openOnboardingPopup]);
767
807
  const handleConnectClick = (e) => {
768
808
  e.preventDefault();
769
809
  };
@@ -827,8 +867,7 @@ function PayPalConnectionPage() {
827
867
  clearCachedUrl(env);
828
868
  completedRef.current = false;
829
869
  currentRunId.current = ++runIdRef.current;
830
- const runId = currentRunId.current;
831
- fetchFreshLink(runId, env);
870
+ await generateLinkAndReload(env, currentRunId.current);
832
871
  } catch (e) {
833
872
  console.error(e);
834
873
  setConnState("error");
@@ -839,10 +878,11 @@ function PayPalConnectionPage() {
839
878
  };
840
879
  const handleEnvChange = async (e) => {
841
880
  const next = e.target.value;
881
+ if (next === env || onboardingInProgress) return;
842
882
  completedRef.current = false;
843
- setPopupBlocked(false);
844
883
  clearCachedUrl();
845
- setEnv(next);
884
+ setPopupBlocked(false);
885
+ setConnState("loading");
846
886
  try {
847
887
  await fetch(ENVIRONMENT_ENDPOINT, {
848
888
  method: "POST",
@@ -852,6 +892,7 @@ function PayPalConnectionPage() {
852
892
  });
853
893
  } catch {
854
894
  }
895
+ setEnv(next);
855
896
  };
856
897
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6", children: [
857
898
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
@@ -1085,6 +1126,9 @@ function PayPalConnectionPage() {
1085
1126
  ` })
1086
1127
  ] });
1087
1128
  }
1129
+ function PayPalGooglePayPage() {
1130
+ return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
1131
+ }
1088
1132
  function PayPalPayLaterMessagingPage() {
1089
1133
  return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
1090
1134
  }
@@ -1302,10 +1346,6 @@ const routeModule = {
1302
1346
  Component: PayPalSettingsIndexRoute,
1303
1347
  path: "/settings/paypal"
1304
1348
  },
1305
- {
1306
- Component: AdvancedCardPaymentsTab,
1307
- path: "/settings/paypal/advanced-card-payments"
1308
- },
1309
1349
  {
1310
1350
  Component: AdditionalSettingsTab,
1311
1351
  path: "/settings/paypal/additional-settings"
@@ -1315,13 +1355,17 @@ const routeModule = {
1315
1355
  path: "/settings/paypal/apple-pay"
1316
1356
  },
1317
1357
  {
1318
- Component: PayPalGooglePayPage,
1319
- path: "/settings/paypal/google-pay"
1358
+ Component: AdvancedCardPaymentsTab,
1359
+ path: "/settings/paypal/advanced-card-payments"
1320
1360
  },
1321
1361
  {
1322
1362
  Component: PayPalConnectionPage,
1323
1363
  path: "/settings/paypal/connection"
1324
1364
  },
1365
+ {
1366
+ Component: PayPalGooglePayPage,
1367
+ path: "/settings/paypal/google-pay"
1368
+ },
1325
1369
  {
1326
1370
  Component: PayPalPayLaterMessagingPage,
1327
1371
  path: "/settings/paypal/pay-later-messaging"