@easypayment/medusa-paypal-ui 1.2.8 → 1.3.0
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/CHANGELOG.md +82 -0
- package/LICENSE +21 -1
- package/README.md +8 -2
- package/dist/index.cjs +605 -676
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -28
- package/dist/index.d.ts +101 -28
- package/dist/index.mjs +601 -676
- package/dist/index.mjs.map +1 -1
- package/dist/order.cjs +11 -8
- package/dist/order.cjs.map +1 -1
- package/dist/order.d.cts +1 -1
- package/dist/order.d.ts +1 -1
- package/dist/order.mjs +10 -8
- package/dist/order.mjs.map +1 -1
- package/package.json +43 -4
- package/src/adapters/MedusaNextPayPalAdapter.tsx +48 -10
- package/src/client/config-cache.ts +96 -0
- package/src/client/http.ts +24 -5
- package/src/client/paypal.ts +28 -6
- package/src/components/PayPalAdvancedCard.tsx +88 -214
- package/src/components/PayPalPaymentSection.tsx +17 -6
- package/src/components/PayPalProvider.tsx +4 -1
- package/src/components/PayPalSmartButtons.tsx +92 -224
- package/src/components/internal/ui.tsx +221 -0
- package/src/hooks/usePayPalConfig.ts +43 -32
- package/src/hooks/usePayPalPaymentMethods.ts +59 -54
- package/src/index.ts +4 -0
- package/src/order.ts +16 -8
- package/src/utils/processing-overlay.ts +25 -21
package/dist/index.mjs
CHANGED
|
@@ -51,7 +51,7 @@ function createHttpClient(opts) {
|
|
|
51
51
|
if (opts.publishableApiKey) {
|
|
52
52
|
headers["x-publishable-api-key"] = opts.publishableApiKey;
|
|
53
53
|
}
|
|
54
|
-
const timeoutMs = 3e4;
|
|
54
|
+
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
55
55
|
const controller = new AbortController();
|
|
56
56
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
57
57
|
const callerSignal = init?.signal ?? null;
|
|
@@ -108,14 +108,18 @@ function createHttpClient(opts) {
|
|
|
108
108
|
}
|
|
109
109
|
const contentType = res.headers.get("content-type") || "";
|
|
110
110
|
if (!contentType.includes("application/json")) {
|
|
111
|
-
throw new
|
|
112
|
-
`[PayPal] Unexpected non-JSON response (${contentType}) from ${path}
|
|
111
|
+
throw new HttpError(
|
|
112
|
+
`[PayPal] Unexpected non-JSON response (${contentType}) from ${path}`,
|
|
113
|
+
res.status
|
|
113
114
|
);
|
|
114
115
|
}
|
|
115
116
|
try {
|
|
116
117
|
return JSON.parse(text);
|
|
117
118
|
} catch {
|
|
118
|
-
throw new
|
|
119
|
+
throw new HttpError(
|
|
120
|
+
`[PayPal] Failed to parse JSON response from ${path}`,
|
|
121
|
+
res.status
|
|
122
|
+
);
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
async function request(path, init, reqOpts) {
|
|
@@ -150,14 +154,21 @@ function generateIdempotencyKey() {
|
|
|
150
154
|
}
|
|
151
155
|
return `pp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
|
|
152
156
|
}
|
|
153
|
-
async function markPaymentComplete(baseUrl, cartId,
|
|
154
|
-
const
|
|
157
|
+
async function markPaymentComplete(baseUrl, cartId, options) {
|
|
158
|
+
const opts = typeof options === "string" ? { publishableApiKey: options } : options ?? {};
|
|
159
|
+
const http = createHttpClient({
|
|
160
|
+
baseUrl,
|
|
161
|
+
publishableApiKey: opts.publishableApiKey,
|
|
162
|
+
credentials: opts.credentials,
|
|
163
|
+
timeoutMs: opts.timeoutMs
|
|
164
|
+
});
|
|
155
165
|
return http.request(
|
|
156
166
|
`/store/paypal-complete`,
|
|
157
167
|
{
|
|
158
168
|
method: "POST",
|
|
159
169
|
headers: { "Content-Type": "application/json" },
|
|
160
|
-
body: JSON.stringify({ cart_id: cartId })
|
|
170
|
+
body: JSON.stringify({ cart_id: cartId }),
|
|
171
|
+
signal: opts.signal
|
|
161
172
|
},
|
|
162
173
|
{ retries: 3 }
|
|
163
174
|
);
|
|
@@ -169,10 +180,12 @@ function createPayPalStoreApi(opts) {
|
|
|
169
180
|
const q = cartId ? `?cart_id=${encodeURIComponent(cartId)}` : "";
|
|
170
181
|
return http.request(`/store/paypal/config${q}`, { signal });
|
|
171
182
|
},
|
|
172
|
-
getSettings() {
|
|
173
|
-
return http.request(`/store/paypal/settings
|
|
183
|
+
getSettings(signal) {
|
|
184
|
+
return http.request(`/store/paypal/settings`, {
|
|
185
|
+
signal
|
|
186
|
+
});
|
|
174
187
|
},
|
|
175
|
-
createOrder(cartId, isCardPayment = false) {
|
|
188
|
+
createOrder(cartId, isCardPayment = false, signal) {
|
|
176
189
|
return http.request(`/store/paypal/create-order`, {
|
|
177
190
|
method: "POST",
|
|
178
191
|
headers: {
|
|
@@ -185,16 +198,18 @@ function createPayPalStoreApi(opts) {
|
|
|
185
198
|
body: JSON.stringify({
|
|
186
199
|
cart_id: cartId,
|
|
187
200
|
is_card_payment: isCardPayment
|
|
188
|
-
})
|
|
201
|
+
}),
|
|
202
|
+
signal
|
|
189
203
|
});
|
|
190
204
|
},
|
|
191
|
-
captureOrder(cartId, orderId) {
|
|
205
|
+
captureOrder(cartId, orderId, signal) {
|
|
192
206
|
return http.request(
|
|
193
207
|
`/store/paypal/capture-order`,
|
|
194
208
|
{
|
|
195
209
|
method: "POST",
|
|
196
210
|
headers: { "Content-Type": "application/json" },
|
|
197
|
-
body: JSON.stringify({ cart_id: cartId, order_id: orderId })
|
|
211
|
+
body: JSON.stringify({ cart_id: cartId, order_id: orderId }),
|
|
212
|
+
signal
|
|
198
213
|
},
|
|
199
214
|
{ retries: 2 }
|
|
200
215
|
);
|
|
@@ -202,39 +217,97 @@ function createPayPalStoreApi(opts) {
|
|
|
202
217
|
};
|
|
203
218
|
}
|
|
204
219
|
|
|
205
|
-
// src/
|
|
206
|
-
import { useEffect, useMemo, useRef, useState } from "react";
|
|
220
|
+
// src/client/config-cache.ts
|
|
207
221
|
var MAX_CACHE_ENTRIES = 50;
|
|
208
|
-
var
|
|
209
|
-
var
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
222
|
+
var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
223
|
+
var SEP = "";
|
|
224
|
+
var cache = /* @__PURE__ */ new Map();
|
|
225
|
+
var inflight = /* @__PURE__ */ new Map();
|
|
226
|
+
function configCacheKey(args) {
|
|
227
|
+
return [
|
|
228
|
+
args.baseUrl,
|
|
229
|
+
args.publishableApiKey ?? "",
|
|
230
|
+
args.cartId ?? "",
|
|
231
|
+
(args.currencyCode ?? "").toLowerCase()
|
|
232
|
+
].join(SEP);
|
|
233
|
+
}
|
|
234
|
+
function getCachedPayPalConfig(key) {
|
|
235
|
+
const hit = cache.get(key);
|
|
236
|
+
if (!hit) return null;
|
|
237
|
+
if (Date.now() - hit.at >= CACHE_TTL_MS) {
|
|
238
|
+
cache.delete(key);
|
|
239
|
+
return null;
|
|
214
240
|
}
|
|
215
|
-
|
|
241
|
+
return hit.config;
|
|
216
242
|
}
|
|
217
|
-
function
|
|
218
|
-
|
|
243
|
+
function invalidatePayPalConfigCache(cartId) {
|
|
244
|
+
if (cartId === void 0) {
|
|
245
|
+
cache.clear();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
for (const key of [...cache.keys()]) {
|
|
249
|
+
if (key.split(SEP)[2] === cartId) cache.delete(key);
|
|
250
|
+
}
|
|
219
251
|
}
|
|
252
|
+
function fetchPayPalConfigShared(key, fetcher) {
|
|
253
|
+
const existing = inflight.get(key);
|
|
254
|
+
if (existing) return existing;
|
|
255
|
+
const p = (async () => {
|
|
256
|
+
try {
|
|
257
|
+
const config = await fetcher();
|
|
258
|
+
if (cache.size >= MAX_CACHE_ENTRIES && !cache.has(key)) {
|
|
259
|
+
const oldest = cache.keys().next().value;
|
|
260
|
+
if (oldest !== void 0) cache.delete(oldest);
|
|
261
|
+
}
|
|
262
|
+
cache.set(key, { config, at: Date.now() });
|
|
263
|
+
return config;
|
|
264
|
+
} finally {
|
|
265
|
+
inflight.delete(key);
|
|
266
|
+
}
|
|
267
|
+
})();
|
|
268
|
+
inflight.set(key, p);
|
|
269
|
+
return p;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/constants.ts
|
|
273
|
+
var PAYPAL_WALLET_PROVIDER_ID = "pp_paypal_paypal";
|
|
274
|
+
var PAYPAL_CARD_PROVIDER_ID = "pp_paypal_card_paypal_card";
|
|
275
|
+
var PAYPAL_PROVIDER_IDS = [
|
|
276
|
+
PAYPAL_WALLET_PROVIDER_ID,
|
|
277
|
+
PAYPAL_CARD_PROVIDER_ID
|
|
278
|
+
];
|
|
279
|
+
function isPayPalProviderId(providerId) {
|
|
280
|
+
if (!providerId) return false;
|
|
281
|
+
return PAYPAL_PROVIDER_IDS.includes(providerId);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/hooks/usePayPalConfig.ts
|
|
285
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
220
286
|
function usePayPalConfig({
|
|
221
287
|
baseUrl,
|
|
222
288
|
publishableApiKey,
|
|
223
289
|
cartId,
|
|
290
|
+
currencyCode,
|
|
291
|
+
credentials,
|
|
224
292
|
enabled = true
|
|
225
293
|
}) {
|
|
226
294
|
const api = useMemo(
|
|
227
|
-
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
228
|
-
[baseUrl, publishableApiKey]
|
|
295
|
+
() => createPayPalStoreApi({ baseUrl, publishableApiKey, credentials }),
|
|
296
|
+
[baseUrl, publishableApiKey, credentials]
|
|
229
297
|
);
|
|
230
|
-
const key =
|
|
231
|
-
|
|
232
|
-
|
|
298
|
+
const key = configCacheKey({
|
|
299
|
+
baseUrl,
|
|
300
|
+
publishableApiKey,
|
|
301
|
+
cartId,
|
|
302
|
+
currencyCode
|
|
303
|
+
});
|
|
304
|
+
const seedConfig = getCachedPayPalConfig(key);
|
|
233
305
|
const [config, setConfig] = useState(seedConfig);
|
|
234
306
|
const [loading, setLoading] = useState(
|
|
235
307
|
seedConfig === null && enabled
|
|
236
308
|
);
|
|
237
309
|
const [error, setError] = useState(null);
|
|
310
|
+
const [retryToken, setRetryToken] = useState(0);
|
|
238
311
|
const fetchIdRef = useRef(0);
|
|
239
312
|
useEffect(() => {
|
|
240
313
|
if (!enabled) {
|
|
@@ -242,27 +315,26 @@ function usePayPalConfig({
|
|
|
242
315
|
setError(null);
|
|
243
316
|
return;
|
|
244
317
|
}
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
setConfig(cached.config);
|
|
318
|
+
const cached = getCachedPayPalConfig(key);
|
|
319
|
+
if (cached) {
|
|
320
|
+
setConfig(cached);
|
|
249
321
|
setLoading(false);
|
|
250
322
|
setError(null);
|
|
251
323
|
return;
|
|
252
324
|
}
|
|
253
325
|
const id = ++fetchIdRef.current;
|
|
254
326
|
let mounted = true;
|
|
255
|
-
const controller = new AbortController();
|
|
256
327
|
setLoading(true);
|
|
257
328
|
setError(null);
|
|
258
329
|
(async () => {
|
|
259
330
|
try {
|
|
260
|
-
const cfg = await
|
|
331
|
+
const cfg = await fetchPayPalConfigShared(
|
|
332
|
+
key,
|
|
333
|
+
() => api.getConfig(cartId)
|
|
334
|
+
);
|
|
261
335
|
if (!mounted || id !== fetchIdRef.current) return;
|
|
262
|
-
cacheSet(k, { config: cfg, at: Date.now() });
|
|
263
336
|
setConfig(cfg);
|
|
264
337
|
} catch (e) {
|
|
265
|
-
if (e instanceof Error && e.name === "AbortError") return;
|
|
266
338
|
if (!mounted || id !== fetchIdRef.current) return;
|
|
267
339
|
setError(
|
|
268
340
|
e instanceof Error ? e.message : "Failed to load PayPal config"
|
|
@@ -273,17 +345,17 @@ function usePayPalConfig({
|
|
|
273
345
|
})();
|
|
274
346
|
return () => {
|
|
275
347
|
mounted = false;
|
|
276
|
-
controller.abort();
|
|
277
348
|
};
|
|
278
|
-
}, [api,
|
|
279
|
-
|
|
349
|
+
}, [api, key, cartId, enabled, retryToken]);
|
|
350
|
+
const retry = useMemo(() => () => setRetryToken((t) => t + 1), []);
|
|
351
|
+
return { config, loading, error, retry };
|
|
280
352
|
}
|
|
281
353
|
|
|
282
354
|
// src/components/PayPalProvider.tsx
|
|
283
355
|
import { useMemo as useMemo2 } from "react";
|
|
284
356
|
import { PayPalScriptProvider } from "@paypal/react-paypal-js";
|
|
285
357
|
import { jsx } from "react/jsx-runtime";
|
|
286
|
-
var BN_CODE = "
|
|
358
|
+
var BN_CODE = "MBJ_Medusa_SI";
|
|
287
359
|
function PayPalProvider(props) {
|
|
288
360
|
const { config, intent = "capture", disableFunding, children } = props;
|
|
289
361
|
const options = useMemo2(() => {
|
|
@@ -377,15 +449,19 @@ function showProcessingOverlay() {
|
|
|
377
449
|
const overlay = document.createElement("div");
|
|
378
450
|
overlay.id = OVERLAY_ID;
|
|
379
451
|
overlay.setAttribute("role", "status");
|
|
380
|
-
overlay.setAttribute("aria-label", "Processing payment");
|
|
381
452
|
overlay.innerHTML = `
|
|
382
453
|
<style>
|
|
383
|
-
@keyframes
|
|
384
|
-
@keyframes
|
|
454
|
+
@keyframes _pp_ov_spin { to { transform: rotate(360deg) } }
|
|
455
|
+
@keyframes _pp_ov_progress { 0% { transform: translateX(-100%) } 100% { transform: translateX(350%) } }
|
|
456
|
+
._pp-ov-spin { animation: _pp_ov_spin .8s linear infinite }
|
|
457
|
+
._pp-ov-progress { animation: _pp_ov_progress 1.5s ease-in-out infinite }
|
|
458
|
+
@media (prefers-reduced-motion: reduce) {
|
|
459
|
+
._pp-ov-spin, ._pp-ov-progress { animation: none }
|
|
460
|
+
}
|
|
385
461
|
</style>
|
|
386
|
-
<div style="position:relative;width:56px;height:56px">
|
|
462
|
+
<div style="position:relative;width:56px;height:56px" aria-hidden="true">
|
|
387
463
|
<div style="position:absolute;inset:0;border-radius:50%;border:3px solid #e5e7eb"></div>
|
|
388
|
-
<div style="position:absolute;inset:0;border-radius:50%;border:3px solid transparent;border-top-color:#0070ba
|
|
464
|
+
<div class="_pp-ov-spin" style="position:absolute;inset:0;border-radius:50%;border:3px solid transparent;border-top-color:#0070ba"></div>
|
|
389
465
|
<svg viewBox="0 0 24 24" fill="none" stroke="#0070ba" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"
|
|
390
466
|
style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:24px;height:24px">
|
|
391
467
|
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
|
@@ -397,8 +473,8 @@ function showProcessingOverlay() {
|
|
|
397
473
|
This may take a few moments. Please do not close<br>or refresh this page.
|
|
398
474
|
</div>
|
|
399
475
|
</div>
|
|
400
|
-
<div style="width:200px;height:3px;background:#e5e7eb;border-radius:3px;overflow:hidden;margin-top:4px">
|
|
401
|
-
<div style="width:40%;height:100%;background:linear-gradient(90deg,#0070ba,#003087);border-radius:3px
|
|
476
|
+
<div style="width:200px;height:3px;background:#e5e7eb;border-radius:3px;overflow:hidden;margin-top:4px" aria-hidden="true">
|
|
477
|
+
<div class="_pp-ov-progress" style="width:40%;height:100%;background:linear-gradient(90deg,#0070ba,#003087);border-radius:3px"></div>
|
|
402
478
|
</div>
|
|
403
479
|
`;
|
|
404
480
|
Object.assign(overlay.style, {
|
|
@@ -419,16 +495,7 @@ function showProcessingOverlay() {
|
|
|
419
495
|
if (location.href !== startUrl) hideProcessingOverlay();
|
|
420
496
|
};
|
|
421
497
|
window.addEventListener("popstate", onNav);
|
|
422
|
-
const
|
|
423
|
-
const origReplace = history.replaceState.bind(history);
|
|
424
|
-
history.pushState = function(...args) {
|
|
425
|
-
origPush(...args);
|
|
426
|
-
onNav();
|
|
427
|
-
};
|
|
428
|
-
history.replaceState = function(...args) {
|
|
429
|
-
origReplace(...args);
|
|
430
|
-
onNav();
|
|
431
|
-
};
|
|
498
|
+
const urlWatcher = window.setInterval(onNav, 250);
|
|
432
499
|
const onPageShow = (e) => {
|
|
433
500
|
if (e.persisted) hideProcessingOverlay();
|
|
434
501
|
};
|
|
@@ -436,8 +503,7 @@ function showProcessingOverlay() {
|
|
|
436
503
|
cleanupNavListener = () => {
|
|
437
504
|
window.removeEventListener("popstate", onNav);
|
|
438
505
|
window.removeEventListener("pageshow", onPageShow);
|
|
439
|
-
|
|
440
|
-
history.replaceState = origReplace;
|
|
506
|
+
window.clearInterval(urlWatcher);
|
|
441
507
|
};
|
|
442
508
|
}
|
|
443
509
|
function hideProcessingOverlay() {
|
|
@@ -447,12 +513,224 @@ function hideProcessingOverlay() {
|
|
|
447
513
|
document.getElementById(OVERLAY_ID)?.remove();
|
|
448
514
|
}
|
|
449
515
|
|
|
450
|
-
// src/components/
|
|
516
|
+
// src/components/internal/ui.tsx
|
|
451
517
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
452
|
-
var
|
|
518
|
+
var ANIMATION_CSS = `
|
|
453
519
|
@keyframes _pp_spin { to { transform: rotate(360deg) } }
|
|
454
520
|
@keyframes _pp_progress { 0% { transform: translateX(-100%) } 100% { transform: translateX(350%) } }
|
|
521
|
+
._pp-spin { animation: _pp_spin .8s linear infinite }
|
|
522
|
+
._pp-spin-sm { animation: _pp_spin .7s linear infinite }
|
|
523
|
+
._pp-progress { animation: _pp_progress 1.5s ease-in-out infinite }
|
|
524
|
+
@media (prefers-reduced-motion: reduce) {
|
|
525
|
+
._pp-spin, ._pp-spin-sm, ._pp-progress { animation: none }
|
|
526
|
+
}
|
|
455
527
|
`;
|
|
528
|
+
function AnimationStyles() {
|
|
529
|
+
return /* @__PURE__ */ jsx3("style", { children: ANIMATION_CSS });
|
|
530
|
+
}
|
|
531
|
+
function ShieldIcon({
|
|
532
|
+
color,
|
|
533
|
+
size = 24,
|
|
534
|
+
style
|
|
535
|
+
}) {
|
|
536
|
+
return /* @__PURE__ */ jsx3(
|
|
537
|
+
"svg",
|
|
538
|
+
{
|
|
539
|
+
viewBox: "0 0 24 24",
|
|
540
|
+
fill: "none",
|
|
541
|
+
stroke: color,
|
|
542
|
+
strokeWidth: "1.8",
|
|
543
|
+
strokeLinecap: "round",
|
|
544
|
+
strokeLinejoin: "round",
|
|
545
|
+
"aria-hidden": "true",
|
|
546
|
+
style: { width: size, height: size, ...style },
|
|
547
|
+
children: /* @__PURE__ */ jsx3("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" })
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
function ProcessingOverlayView({ accent }) {
|
|
552
|
+
return /* @__PURE__ */ jsxs2(
|
|
553
|
+
"div",
|
|
554
|
+
{
|
|
555
|
+
role: "status",
|
|
556
|
+
style: {
|
|
557
|
+
position: "fixed",
|
|
558
|
+
inset: 0,
|
|
559
|
+
zIndex: 9999,
|
|
560
|
+
background: "rgba(255,255,255,0.96)",
|
|
561
|
+
display: "flex",
|
|
562
|
+
flexDirection: "column",
|
|
563
|
+
alignItems: "center",
|
|
564
|
+
justifyContent: "center",
|
|
565
|
+
gap: 20
|
|
566
|
+
},
|
|
567
|
+
children: [
|
|
568
|
+
/* @__PURE__ */ jsxs2("div", { style: { position: "relative", width: 56, height: 56 }, children: [
|
|
569
|
+
/* @__PURE__ */ jsx3(
|
|
570
|
+
"div",
|
|
571
|
+
{
|
|
572
|
+
style: {
|
|
573
|
+
position: "absolute",
|
|
574
|
+
inset: 0,
|
|
575
|
+
borderRadius: "50%",
|
|
576
|
+
border: "3px solid #e5e7eb"
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
),
|
|
580
|
+
/* @__PURE__ */ jsx3(
|
|
581
|
+
"div",
|
|
582
|
+
{
|
|
583
|
+
className: "_pp-spin",
|
|
584
|
+
style: {
|
|
585
|
+
position: "absolute",
|
|
586
|
+
inset: 0,
|
|
587
|
+
borderRadius: "50%",
|
|
588
|
+
border: "3px solid transparent",
|
|
589
|
+
borderTopColor: accent
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
),
|
|
593
|
+
/* @__PURE__ */ jsx3(
|
|
594
|
+
ShieldIcon,
|
|
595
|
+
{
|
|
596
|
+
color: accent,
|
|
597
|
+
style: {
|
|
598
|
+
position: "absolute",
|
|
599
|
+
top: "50%",
|
|
600
|
+
left: "50%",
|
|
601
|
+
transform: "translate(-50%, -50%)"
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
)
|
|
605
|
+
] }),
|
|
606
|
+
/* @__PURE__ */ jsxs2("div", { style: { textAlign: "center" }, children: [
|
|
607
|
+
/* @__PURE__ */ jsx3(
|
|
608
|
+
"div",
|
|
609
|
+
{
|
|
610
|
+
style: {
|
|
611
|
+
fontSize: 18,
|
|
612
|
+
fontWeight: 600,
|
|
613
|
+
color: "#111827",
|
|
614
|
+
letterSpacing: "-0.01em"
|
|
615
|
+
},
|
|
616
|
+
children: "Processing your payment"
|
|
617
|
+
}
|
|
618
|
+
),
|
|
619
|
+
/* @__PURE__ */ jsxs2(
|
|
620
|
+
"div",
|
|
621
|
+
{
|
|
622
|
+
style: {
|
|
623
|
+
fontSize: 14,
|
|
624
|
+
color: "#6b7280",
|
|
625
|
+
marginTop: 6,
|
|
626
|
+
lineHeight: 1.5
|
|
627
|
+
},
|
|
628
|
+
children: [
|
|
629
|
+
"This may take a few moments. Please do not close",
|
|
630
|
+
/* @__PURE__ */ jsx3("br", {}),
|
|
631
|
+
"or refresh this page."
|
|
632
|
+
]
|
|
633
|
+
}
|
|
634
|
+
)
|
|
635
|
+
] }),
|
|
636
|
+
/* @__PURE__ */ jsx3(
|
|
637
|
+
"div",
|
|
638
|
+
{
|
|
639
|
+
style: {
|
|
640
|
+
width: 200,
|
|
641
|
+
height: 3,
|
|
642
|
+
background: "#e5e7eb",
|
|
643
|
+
borderRadius: 3,
|
|
644
|
+
overflow: "hidden",
|
|
645
|
+
marginTop: 4
|
|
646
|
+
},
|
|
647
|
+
"aria-hidden": "true",
|
|
648
|
+
children: /* @__PURE__ */ jsx3(
|
|
649
|
+
"div",
|
|
650
|
+
{
|
|
651
|
+
className: "_pp-progress",
|
|
652
|
+
style: {
|
|
653
|
+
width: "40%",
|
|
654
|
+
height: "100%",
|
|
655
|
+
background: `linear-gradient(90deg, ${accent}, #003087)`,
|
|
656
|
+
borderRadius: 3
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
)
|
|
660
|
+
}
|
|
661
|
+
)
|
|
662
|
+
]
|
|
663
|
+
}
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
function LoadingCard({ label }) {
|
|
667
|
+
return /* @__PURE__ */ jsxs2(
|
|
668
|
+
"div",
|
|
669
|
+
{
|
|
670
|
+
role: "status",
|
|
671
|
+
style: {
|
|
672
|
+
display: "flex",
|
|
673
|
+
alignItems: "center",
|
|
674
|
+
justifyContent: "center",
|
|
675
|
+
gap: 10,
|
|
676
|
+
padding: "18px 16px",
|
|
677
|
+
background: "#f9fafb",
|
|
678
|
+
border: "1px solid #e5e7eb",
|
|
679
|
+
borderRadius: 8,
|
|
680
|
+
minHeight: 55
|
|
681
|
+
},
|
|
682
|
+
children: [
|
|
683
|
+
/* @__PURE__ */ jsx3(
|
|
684
|
+
"div",
|
|
685
|
+
{
|
|
686
|
+
className: "_pp-spin-sm",
|
|
687
|
+
"aria-hidden": "true",
|
|
688
|
+
style: {
|
|
689
|
+
width: 22,
|
|
690
|
+
height: 22,
|
|
691
|
+
borderRadius: "50%",
|
|
692
|
+
border: "2.5px solid #e5e7eb",
|
|
693
|
+
borderTopColor: "#0070ba",
|
|
694
|
+
flexShrink: 0
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
),
|
|
698
|
+
/* @__PURE__ */ jsx3("div", { style: { fontSize: 13, fontWeight: 500, color: "#6b7280" }, children: label })
|
|
699
|
+
]
|
|
700
|
+
}
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
function ErrorBanner({
|
|
704
|
+
children,
|
|
705
|
+
style
|
|
706
|
+
}) {
|
|
707
|
+
return /* @__PURE__ */ jsxs2(
|
|
708
|
+
"div",
|
|
709
|
+
{
|
|
710
|
+
role: "alert",
|
|
711
|
+
style: {
|
|
712
|
+
display: "flex",
|
|
713
|
+
alignItems: "flex-start",
|
|
714
|
+
gap: 8,
|
|
715
|
+
padding: "10px 14px",
|
|
716
|
+
background: "#fef2f2",
|
|
717
|
+
border: "1px solid #fecaca",
|
|
718
|
+
borderRadius: 8,
|
|
719
|
+
fontSize: 13,
|
|
720
|
+
color: "#b91c1c",
|
|
721
|
+
lineHeight: 1.5,
|
|
722
|
+
...style
|
|
723
|
+
},
|
|
724
|
+
children: [
|
|
725
|
+
/* @__PURE__ */ jsx3("span", { "aria-hidden": "true", style: { flexShrink: 0, fontSize: 15 }, children: "\u26A0\uFE0F" }),
|
|
726
|
+
/* @__PURE__ */ jsx3("span", { children })
|
|
727
|
+
]
|
|
728
|
+
}
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// src/components/PayPalSmartButtons.tsx
|
|
733
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
456
734
|
var BUTTON_WIDTH_MAP = {
|
|
457
735
|
small: "300px",
|
|
458
736
|
medium: "400px",
|
|
@@ -460,24 +738,52 @@ var BUTTON_WIDTH_MAP = {
|
|
|
460
738
|
responsive: "100%"
|
|
461
739
|
};
|
|
462
740
|
function PayPalSmartButtons(props) {
|
|
463
|
-
const {
|
|
741
|
+
const {
|
|
742
|
+
baseUrl,
|
|
743
|
+
publishableApiKey,
|
|
744
|
+
credentials,
|
|
745
|
+
cartId,
|
|
746
|
+
config,
|
|
747
|
+
onPaid,
|
|
748
|
+
onError
|
|
749
|
+
} = props;
|
|
464
750
|
const api = useMemo3(
|
|
465
|
-
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
466
|
-
[baseUrl, publishableApiKey]
|
|
751
|
+
() => createPayPalStoreApi({ baseUrl, publishableApiKey, credentials }),
|
|
752
|
+
[baseUrl, publishableApiKey, credentials]
|
|
467
753
|
);
|
|
468
754
|
const [error, setError] = useState2(null);
|
|
469
755
|
const [processing, setProcessing] = useState2(false);
|
|
756
|
+
const processingRef = useRef2(false);
|
|
757
|
+
const [domOverlayUp, setDomOverlayUp] = useState2(false);
|
|
470
758
|
const [buttonsReady, setButtonsReady] = useState2(false);
|
|
471
759
|
const [loadTimedOut, setLoadTimedOut] = useState2(false);
|
|
472
760
|
const capturedRef = useRef2(null);
|
|
473
761
|
const [completionPending, setCompletionPending] = useState2(false);
|
|
474
762
|
const [{ isPending, isResolved, isRejected }] = usePayPalScriptReducer();
|
|
763
|
+
const startProcessing = useCallback(() => {
|
|
764
|
+
processingRef.current = true;
|
|
765
|
+
setProcessing(true);
|
|
766
|
+
}, []);
|
|
767
|
+
const stopProcessing = useCallback(() => {
|
|
768
|
+
hideProcessingOverlay();
|
|
769
|
+
setDomOverlayUp(false);
|
|
770
|
+
processingRef.current = false;
|
|
771
|
+
setProcessing(false);
|
|
772
|
+
}, []);
|
|
773
|
+
const showOverlay = useCallback(() => {
|
|
774
|
+
showProcessingOverlay();
|
|
775
|
+
setDomOverlayUp(true);
|
|
776
|
+
}, []);
|
|
475
777
|
const handleInit = useCallback(() => {
|
|
476
778
|
setButtonsReady(true);
|
|
477
779
|
}, []);
|
|
478
780
|
useEffect2(() => {
|
|
479
781
|
const onPageShow = (e) => {
|
|
480
|
-
if (e.persisted)
|
|
782
|
+
if (e.persisted) {
|
|
783
|
+
processingRef.current = false;
|
|
784
|
+
setProcessing(false);
|
|
785
|
+
setDomOverlayUp(false);
|
|
786
|
+
}
|
|
481
787
|
};
|
|
482
788
|
window.addEventListener("pageshow", onPageShow);
|
|
483
789
|
return () => window.removeEventListener("pageshow", onPageShow);
|
|
@@ -499,234 +805,46 @@ function PayPalSmartButtons(props) {
|
|
|
499
805
|
const finalizeCapturedPayment = useCallback(async () => {
|
|
500
806
|
const captured = capturedRef.current;
|
|
501
807
|
if (!captured) return;
|
|
502
|
-
|
|
503
|
-
|
|
808
|
+
startProcessing();
|
|
809
|
+
showOverlay();
|
|
504
810
|
setError(null);
|
|
505
811
|
try {
|
|
506
|
-
const completeResult = await markPaymentComplete(
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
);
|
|
812
|
+
const completeResult = await markPaymentComplete(baseUrl, cartId, {
|
|
813
|
+
publishableApiKey,
|
|
814
|
+
credentials
|
|
815
|
+
});
|
|
511
816
|
clearCartCaptured(cartId);
|
|
512
817
|
await onPaid?.({ ...captured, ...completeResult });
|
|
513
818
|
setCompletionPending(false);
|
|
514
819
|
} catch (e) {
|
|
515
820
|
if (isNextRouterError(e)) return;
|
|
516
|
-
|
|
517
|
-
setProcessing(false);
|
|
821
|
+
stopProcessing();
|
|
518
822
|
setCompletionPending(true);
|
|
519
823
|
const msg = "Your payment was received, but finalizing your order failed. Please use the Retry button below \u2014 do not pay again.";
|
|
520
824
|
setError(msg);
|
|
521
825
|
onError?.(msg);
|
|
522
826
|
}
|
|
523
|
-
}, [
|
|
827
|
+
}, [
|
|
828
|
+
baseUrl,
|
|
829
|
+
cartId,
|
|
830
|
+
publishableApiKey,
|
|
831
|
+
credentials,
|
|
832
|
+
onPaid,
|
|
833
|
+
onError,
|
|
834
|
+
startProcessing,
|
|
835
|
+
showOverlay,
|
|
836
|
+
stopProcessing
|
|
837
|
+
]);
|
|
524
838
|
const showSpinner = (isPending || isResolved && !buttonsReady) && !loadTimedOut;
|
|
525
839
|
if (!config.currency_supported) return null;
|
|
526
840
|
const containerWidth = BUTTON_WIDTH_MAP[config.button_width ?? "responsive"] ?? "100%";
|
|
527
|
-
return /* @__PURE__ */
|
|
528
|
-
/* @__PURE__ */
|
|
529
|
-
processing && /* @__PURE__ */
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
style: {
|
|
535
|
-
position: "fixed",
|
|
536
|
-
inset: 0,
|
|
537
|
-
zIndex: 9999,
|
|
538
|
-
background: "rgba(255,255,255,0.96)",
|
|
539
|
-
display: "flex",
|
|
540
|
-
flexDirection: "column",
|
|
541
|
-
alignItems: "center",
|
|
542
|
-
justifyContent: "center",
|
|
543
|
-
gap: 20
|
|
544
|
-
},
|
|
545
|
-
children: [
|
|
546
|
-
/* @__PURE__ */ jsxs2("div", { style: { position: "relative", width: 56, height: 56 }, children: [
|
|
547
|
-
/* @__PURE__ */ jsx3(
|
|
548
|
-
"div",
|
|
549
|
-
{
|
|
550
|
-
style: {
|
|
551
|
-
position: "absolute",
|
|
552
|
-
inset: 0,
|
|
553
|
-
borderRadius: "50%",
|
|
554
|
-
border: "3px solid #e5e7eb"
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
),
|
|
558
|
-
/* @__PURE__ */ jsx3(
|
|
559
|
-
"div",
|
|
560
|
-
{
|
|
561
|
-
style: {
|
|
562
|
-
position: "absolute",
|
|
563
|
-
inset: 0,
|
|
564
|
-
borderRadius: "50%",
|
|
565
|
-
border: "3px solid transparent",
|
|
566
|
-
borderTopColor: "#0070ba",
|
|
567
|
-
animation: "_pp_spin .8s linear infinite"
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
),
|
|
571
|
-
/* @__PURE__ */ jsx3(
|
|
572
|
-
"svg",
|
|
573
|
-
{
|
|
574
|
-
viewBox: "0 0 24 24",
|
|
575
|
-
fill: "none",
|
|
576
|
-
stroke: "#0070ba",
|
|
577
|
-
strokeWidth: "1.8",
|
|
578
|
-
strokeLinecap: "round",
|
|
579
|
-
strokeLinejoin: "round",
|
|
580
|
-
style: {
|
|
581
|
-
position: "absolute",
|
|
582
|
-
top: "50%",
|
|
583
|
-
left: "50%",
|
|
584
|
-
transform: "translate(-50%, -50%)",
|
|
585
|
-
width: 24,
|
|
586
|
-
height: 24
|
|
587
|
-
},
|
|
588
|
-
children: /* @__PURE__ */ jsx3("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" })
|
|
589
|
-
}
|
|
590
|
-
)
|
|
591
|
-
] }),
|
|
592
|
-
/* @__PURE__ */ jsxs2("div", { style: { textAlign: "center" }, children: [
|
|
593
|
-
/* @__PURE__ */ jsx3(
|
|
594
|
-
"div",
|
|
595
|
-
{
|
|
596
|
-
style: {
|
|
597
|
-
fontSize: 18,
|
|
598
|
-
fontWeight: 600,
|
|
599
|
-
color: "#111827",
|
|
600
|
-
letterSpacing: "-0.01em"
|
|
601
|
-
},
|
|
602
|
-
children: "Processing your payment"
|
|
603
|
-
}
|
|
604
|
-
),
|
|
605
|
-
/* @__PURE__ */ jsxs2(
|
|
606
|
-
"div",
|
|
607
|
-
{
|
|
608
|
-
style: {
|
|
609
|
-
fontSize: 14,
|
|
610
|
-
color: "#6b7280",
|
|
611
|
-
marginTop: 6,
|
|
612
|
-
lineHeight: 1.5
|
|
613
|
-
},
|
|
614
|
-
children: [
|
|
615
|
-
"This may take a few moments. Please do not close",
|
|
616
|
-
/* @__PURE__ */ jsx3("br", {}),
|
|
617
|
-
"or refresh this page."
|
|
618
|
-
]
|
|
619
|
-
}
|
|
620
|
-
)
|
|
621
|
-
] }),
|
|
622
|
-
/* @__PURE__ */ jsx3(
|
|
623
|
-
"div",
|
|
624
|
-
{
|
|
625
|
-
style: {
|
|
626
|
-
width: 200,
|
|
627
|
-
height: 3,
|
|
628
|
-
background: "#e5e7eb",
|
|
629
|
-
borderRadius: 3,
|
|
630
|
-
overflow: "hidden",
|
|
631
|
-
marginTop: 4
|
|
632
|
-
},
|
|
633
|
-
children: /* @__PURE__ */ jsx3(
|
|
634
|
-
"div",
|
|
635
|
-
{
|
|
636
|
-
style: {
|
|
637
|
-
width: "40%",
|
|
638
|
-
height: "100%",
|
|
639
|
-
background: "linear-gradient(90deg, #0070ba, #003087)",
|
|
640
|
-
borderRadius: 3,
|
|
641
|
-
animation: "_pp_progress 1.5s ease-in-out infinite"
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
)
|
|
645
|
-
}
|
|
646
|
-
)
|
|
647
|
-
]
|
|
648
|
-
}
|
|
649
|
-
),
|
|
650
|
-
showSpinner && /* @__PURE__ */ jsxs2(
|
|
651
|
-
"div",
|
|
652
|
-
{
|
|
653
|
-
role: "status",
|
|
654
|
-
"aria-label": "Loading PayPal",
|
|
655
|
-
style: {
|
|
656
|
-
display: "flex",
|
|
657
|
-
alignItems: "center",
|
|
658
|
-
justifyContent: "center",
|
|
659
|
-
gap: 10,
|
|
660
|
-
padding: "18px 16px",
|
|
661
|
-
background: "#f9fafb",
|
|
662
|
-
border: "1px solid #e5e7eb",
|
|
663
|
-
borderRadius: 8,
|
|
664
|
-
minHeight: 55
|
|
665
|
-
},
|
|
666
|
-
children: [
|
|
667
|
-
/* @__PURE__ */ jsx3(
|
|
668
|
-
"div",
|
|
669
|
-
{
|
|
670
|
-
style: {
|
|
671
|
-
width: 22,
|
|
672
|
-
height: 22,
|
|
673
|
-
borderRadius: "50%",
|
|
674
|
-
border: "2.5px solid #e5e7eb",
|
|
675
|
-
borderTopColor: "#0070ba",
|
|
676
|
-
animation: "_pp_spin .7s linear infinite",
|
|
677
|
-
flexShrink: 0
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
),
|
|
681
|
-
/* @__PURE__ */ jsx3("div", { style: { fontSize: 13, fontWeight: 500, color: "#6b7280" }, children: "Loading PayPal\u2026" })
|
|
682
|
-
]
|
|
683
|
-
}
|
|
684
|
-
),
|
|
685
|
-
loadTimedOut && !buttonsReady && !isRejected && /* @__PURE__ */ jsxs2(
|
|
686
|
-
"div",
|
|
687
|
-
{
|
|
688
|
-
role: "alert",
|
|
689
|
-
style: {
|
|
690
|
-
display: "flex",
|
|
691
|
-
alignItems: "flex-start",
|
|
692
|
-
gap: 8,
|
|
693
|
-
padding: "10px 14px",
|
|
694
|
-
background: "#fef2f2",
|
|
695
|
-
border: "1px solid #fecaca",
|
|
696
|
-
borderRadius: 8,
|
|
697
|
-
fontSize: 13,
|
|
698
|
-
color: "#b91c1c",
|
|
699
|
-
lineHeight: 1.5
|
|
700
|
-
},
|
|
701
|
-
children: [
|
|
702
|
-
/* @__PURE__ */ jsx3("span", { style: { flexShrink: 0, fontSize: 15 }, children: "\u26A0\uFE0F" }),
|
|
703
|
-
/* @__PURE__ */ jsx3("span", { children: "PayPal is not available for this purchase. Please try a different payment method." })
|
|
704
|
-
]
|
|
705
|
-
}
|
|
706
|
-
),
|
|
707
|
-
isRejected && /* @__PURE__ */ jsxs2(
|
|
708
|
-
"div",
|
|
709
|
-
{
|
|
710
|
-
role: "alert",
|
|
711
|
-
style: {
|
|
712
|
-
display: "flex",
|
|
713
|
-
alignItems: "flex-start",
|
|
714
|
-
gap: 8,
|
|
715
|
-
padding: "10px 14px",
|
|
716
|
-
background: "#fef2f2",
|
|
717
|
-
border: "1px solid #fecaca",
|
|
718
|
-
borderRadius: 8,
|
|
719
|
-
fontSize: 13,
|
|
720
|
-
color: "#b91c1c",
|
|
721
|
-
lineHeight: 1.5
|
|
722
|
-
},
|
|
723
|
-
children: [
|
|
724
|
-
/* @__PURE__ */ jsx3("span", { style: { flexShrink: 0, fontSize: 15 }, children: "\u26A0\uFE0F" }),
|
|
725
|
-
/* @__PURE__ */ jsx3("span", { children: "PayPal failed to load. Please refresh the page or try a different payment method." })
|
|
726
|
-
]
|
|
727
|
-
}
|
|
728
|
-
),
|
|
729
|
-
config.environment === "sandbox" && buttonsReady && /* @__PURE__ */ jsxs2(
|
|
841
|
+
return /* @__PURE__ */ jsxs3("div", { style: { width: containerWidth, position: "relative" }, children: [
|
|
842
|
+
/* @__PURE__ */ jsx4(AnimationStyles, {}),
|
|
843
|
+
processing && !domOverlayUp && /* @__PURE__ */ jsx4(ProcessingOverlayView, { accent: "#0070ba" }),
|
|
844
|
+
showSpinner && /* @__PURE__ */ jsx4(LoadingCard, { label: "Loading PayPal\u2026" }),
|
|
845
|
+
loadTimedOut && !buttonsReady && !isRejected && /* @__PURE__ */ jsx4(ErrorBanner, { children: "PayPal is not available for this purchase. Please try a different payment method." }),
|
|
846
|
+
isRejected && /* @__PURE__ */ jsx4(ErrorBanner, { children: "PayPal failed to load. Please refresh the page or try a different payment method." }),
|
|
847
|
+
config.environment === "sandbox" && buttonsReady && /* @__PURE__ */ jsxs3(
|
|
730
848
|
"div",
|
|
731
849
|
{
|
|
732
850
|
style: {
|
|
@@ -743,7 +861,7 @@ function PayPalSmartButtons(props) {
|
|
|
743
861
|
marginBottom: 10
|
|
744
862
|
},
|
|
745
863
|
children: [
|
|
746
|
-
/* @__PURE__ */
|
|
864
|
+
/* @__PURE__ */ jsxs3(
|
|
747
865
|
"svg",
|
|
748
866
|
{
|
|
749
867
|
width: "16",
|
|
@@ -753,18 +871,19 @@ function PayPalSmartButtons(props) {
|
|
|
753
871
|
stroke: "#1e40af",
|
|
754
872
|
strokeWidth: "2",
|
|
755
873
|
strokeLinecap: "round",
|
|
874
|
+
"aria-hidden": "true",
|
|
756
875
|
style: { flexShrink: 0, marginTop: 1 },
|
|
757
876
|
children: [
|
|
758
|
-
/* @__PURE__ */
|
|
759
|
-
/* @__PURE__ */
|
|
877
|
+
/* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "10" }),
|
|
878
|
+
/* @__PURE__ */ jsx4("path", { d: "M12 8v4M12 16h.01" })
|
|
760
879
|
]
|
|
761
880
|
}
|
|
762
881
|
),
|
|
763
|
-
/* @__PURE__ */
|
|
882
|
+
/* @__PURE__ */ jsx4("span", { children: "Sandbox mode \u2014 you will not be charged. Use your PayPal sandbox account to complete the payment." })
|
|
764
883
|
]
|
|
765
884
|
}
|
|
766
885
|
),
|
|
767
|
-
isResolved && !completionPending && /* @__PURE__ */
|
|
886
|
+
isResolved && !completionPending && /* @__PURE__ */ jsx4(
|
|
768
887
|
"div",
|
|
769
888
|
{
|
|
770
889
|
style: buttonsReady ? void 0 : {
|
|
@@ -773,7 +892,7 @@ function PayPalSmartButtons(props) {
|
|
|
773
892
|
opacity: 0,
|
|
774
893
|
pointerEvents: "none"
|
|
775
894
|
},
|
|
776
|
-
children: /* @__PURE__ */
|
|
895
|
+
children: /* @__PURE__ */ jsx4(
|
|
777
896
|
PayPalButtons,
|
|
778
897
|
{
|
|
779
898
|
forceReRender: [config.currency, config.intent, cartId],
|
|
@@ -786,7 +905,8 @@ function PayPalSmartButtons(props) {
|
|
|
786
905
|
height: config.button_height
|
|
787
906
|
},
|
|
788
907
|
createOrder: async () => {
|
|
789
|
-
if (
|
|
908
|
+
if (processingRef.current)
|
|
909
|
+
throw new Error("Payment already processing");
|
|
790
910
|
if (capturedRef.current) {
|
|
791
911
|
void finalizeCapturedPayment();
|
|
792
912
|
throw new Error(
|
|
@@ -794,19 +914,19 @@ function PayPalSmartButtons(props) {
|
|
|
794
914
|
);
|
|
795
915
|
}
|
|
796
916
|
setError(null);
|
|
797
|
-
|
|
917
|
+
startProcessing();
|
|
798
918
|
try {
|
|
799
919
|
const r = await api.createOrder(cartId);
|
|
800
920
|
return r.id;
|
|
801
921
|
} catch (e) {
|
|
802
|
-
|
|
922
|
+
stopProcessing();
|
|
803
923
|
throw e;
|
|
804
924
|
}
|
|
805
925
|
},
|
|
806
926
|
onApprove: async (data) => {
|
|
807
927
|
try {
|
|
808
|
-
|
|
809
|
-
|
|
928
|
+
startProcessing();
|
|
929
|
+
showOverlay();
|
|
810
930
|
setError(null);
|
|
811
931
|
const orderId = String(data?.orderID || "");
|
|
812
932
|
if (!orderId)
|
|
@@ -818,8 +938,7 @@ function PayPalSmartButtons(props) {
|
|
|
818
938
|
markCartCaptured(cartId);
|
|
819
939
|
} catch (e) {
|
|
820
940
|
if (isNextRouterError(e)) return;
|
|
821
|
-
|
|
822
|
-
setProcessing(false);
|
|
941
|
+
stopProcessing();
|
|
823
942
|
const msg = e instanceof Error ? e.message : "Payment capture failed";
|
|
824
943
|
setError(msg);
|
|
825
944
|
onError?.(msg);
|
|
@@ -828,12 +947,10 @@ function PayPalSmartButtons(props) {
|
|
|
828
947
|
await finalizeCapturedPayment();
|
|
829
948
|
},
|
|
830
949
|
onCancel: () => {
|
|
831
|
-
|
|
832
|
-
setProcessing(false);
|
|
950
|
+
stopProcessing();
|
|
833
951
|
},
|
|
834
952
|
onError: (err) => {
|
|
835
|
-
|
|
836
|
-
setProcessing(false);
|
|
953
|
+
stopProcessing();
|
|
837
954
|
const msg = err instanceof Error ? err.message : err?.message || "PayPal error";
|
|
838
955
|
setError(msg);
|
|
839
956
|
onError?.(msg);
|
|
@@ -842,7 +959,7 @@ function PayPalSmartButtons(props) {
|
|
|
842
959
|
)
|
|
843
960
|
}
|
|
844
961
|
),
|
|
845
|
-
completionPending && /* @__PURE__ */
|
|
962
|
+
completionPending && /* @__PURE__ */ jsx4(
|
|
846
963
|
"button",
|
|
847
964
|
{
|
|
848
965
|
type: "button",
|
|
@@ -865,29 +982,7 @@ function PayPalSmartButtons(props) {
|
|
|
865
982
|
children: "Retry \u2014 finish placing my order"
|
|
866
983
|
}
|
|
867
984
|
),
|
|
868
|
-
error ? /* @__PURE__ */
|
|
869
|
-
"div",
|
|
870
|
-
{
|
|
871
|
-
role: "alert",
|
|
872
|
-
style: {
|
|
873
|
-
marginTop: 10,
|
|
874
|
-
display: "flex",
|
|
875
|
-
alignItems: "flex-start",
|
|
876
|
-
gap: 8,
|
|
877
|
-
padding: "10px 14px",
|
|
878
|
-
background: "#fef2f2",
|
|
879
|
-
border: "1px solid #fecaca",
|
|
880
|
-
borderRadius: 8,
|
|
881
|
-
fontSize: 13,
|
|
882
|
-
color: "#b91c1c",
|
|
883
|
-
lineHeight: 1.5
|
|
884
|
-
},
|
|
885
|
-
children: [
|
|
886
|
-
/* @__PURE__ */ jsx3("span", { style: { flexShrink: 0, fontSize: 15 }, children: "\u26A0\uFE0F" }),
|
|
887
|
-
/* @__PURE__ */ jsx3("span", { children: error })
|
|
888
|
-
]
|
|
889
|
-
}
|
|
890
|
-
) : null
|
|
985
|
+
error ? /* @__PURE__ */ jsx4(ErrorBanner, { style: { marginTop: 10 }, children: error }) : null
|
|
891
986
|
] });
|
|
892
987
|
}
|
|
893
988
|
|
|
@@ -901,11 +996,7 @@ import {
|
|
|
901
996
|
usePayPalCardFields,
|
|
902
997
|
usePayPalScriptReducer as usePayPalScriptReducer2
|
|
903
998
|
} from "@paypal/react-paypal-js";
|
|
904
|
-
import { jsx as
|
|
905
|
-
var SPIN_STYLE2 = `
|
|
906
|
-
@keyframes _pp_spin { to { transform: rotate(360deg) } }
|
|
907
|
-
@keyframes _pp_progress { 0% { transform: translateX(-100%) } 100% { transform: translateX(350%) } }
|
|
908
|
-
`;
|
|
999
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
909
1000
|
var cardStyle = {
|
|
910
1001
|
input: {
|
|
911
1002
|
"font-size": "15px",
|
|
@@ -950,18 +1041,19 @@ var labelStyle = {
|
|
|
950
1041
|
};
|
|
951
1042
|
function SubmitButton({
|
|
952
1043
|
disabled,
|
|
1044
|
+
busy,
|
|
953
1045
|
label,
|
|
954
1046
|
onSubmit,
|
|
955
1047
|
onSubmitError
|
|
956
1048
|
}) {
|
|
957
1049
|
const { cardFieldsForm } = usePayPalCardFields();
|
|
958
1050
|
const isDisabled = disabled || !cardFieldsForm;
|
|
959
|
-
return /* @__PURE__ */
|
|
1051
|
+
return /* @__PURE__ */ jsx5(
|
|
960
1052
|
"button",
|
|
961
1053
|
{
|
|
962
1054
|
type: "button",
|
|
963
1055
|
disabled: isDisabled,
|
|
964
|
-
"aria-busy":
|
|
1056
|
+
"aria-busy": busy,
|
|
965
1057
|
onClick: () => {
|
|
966
1058
|
onSubmit();
|
|
967
1059
|
Promise.resolve(cardFieldsForm?.submit()).catch((e) => {
|
|
@@ -1004,20 +1096,34 @@ function SubmitButton({
|
|
|
1004
1096
|
);
|
|
1005
1097
|
}
|
|
1006
1098
|
function PayPalAdvancedCard(props) {
|
|
1007
|
-
const {
|
|
1099
|
+
const {
|
|
1100
|
+
baseUrl,
|
|
1101
|
+
publishableApiKey,
|
|
1102
|
+
credentials,
|
|
1103
|
+
cartId,
|
|
1104
|
+
config,
|
|
1105
|
+
onPaid,
|
|
1106
|
+
onError
|
|
1107
|
+
} = props;
|
|
1008
1108
|
const api = useMemo4(
|
|
1009
|
-
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
1010
|
-
[baseUrl, publishableApiKey]
|
|
1109
|
+
() => createPayPalStoreApi({ baseUrl, publishableApiKey, credentials }),
|
|
1110
|
+
[baseUrl, publishableApiKey, credentials]
|
|
1011
1111
|
);
|
|
1012
1112
|
const [error, setError] = useState3(null);
|
|
1013
1113
|
const [submitting, setSubmitting] = useState3(false);
|
|
1014
1114
|
const submittingRef = useRef3(false);
|
|
1015
1115
|
const creatingOrderRef = useRef3(false);
|
|
1116
|
+
const [domOverlayUp, setDomOverlayUp] = useState3(false);
|
|
1016
1117
|
const capturedRef = useRef3(null);
|
|
1017
1118
|
const [completionPending, setCompletionPending] = useState3(false);
|
|
1018
1119
|
const [{ isPending, isResolved, isRejected }] = usePayPalScriptReducer2();
|
|
1120
|
+
const showOverlay = React3.useCallback(() => {
|
|
1121
|
+
showProcessingOverlay();
|
|
1122
|
+
setDomOverlayUp(true);
|
|
1123
|
+
}, []);
|
|
1019
1124
|
const resetSubmitState = React3.useCallback(() => {
|
|
1020
1125
|
hideProcessingOverlay();
|
|
1126
|
+
setDomOverlayUp(false);
|
|
1021
1127
|
creatingOrderRef.current = false;
|
|
1022
1128
|
submittingRef.current = false;
|
|
1023
1129
|
setSubmitting(false);
|
|
@@ -1028,6 +1134,7 @@ function PayPalAdvancedCard(props) {
|
|
|
1028
1134
|
creatingOrderRef.current = false;
|
|
1029
1135
|
submittingRef.current = false;
|
|
1030
1136
|
setSubmitting(false);
|
|
1137
|
+
setDomOverlayUp(false);
|
|
1031
1138
|
}
|
|
1032
1139
|
};
|
|
1033
1140
|
window.addEventListener("pageshow", onPageShow);
|
|
@@ -1045,14 +1152,13 @@ function PayPalAdvancedCard(props) {
|
|
|
1045
1152
|
const captured = capturedRef.current;
|
|
1046
1153
|
if (!captured) return;
|
|
1047
1154
|
setSubmitting(true);
|
|
1048
|
-
|
|
1155
|
+
showOverlay();
|
|
1049
1156
|
setError(null);
|
|
1050
1157
|
try {
|
|
1051
|
-
const completeResult = await markPaymentComplete(
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
);
|
|
1158
|
+
const completeResult = await markPaymentComplete(baseUrl, cartId, {
|
|
1159
|
+
publishableApiKey,
|
|
1160
|
+
credentials
|
|
1161
|
+
});
|
|
1056
1162
|
clearCartCaptured(cartId);
|
|
1057
1163
|
await onPaid?.({ ...captured, ...completeResult });
|
|
1058
1164
|
setCompletionPending(false);
|
|
@@ -1064,34 +1170,22 @@ function PayPalAdvancedCard(props) {
|
|
|
1064
1170
|
setError(msg);
|
|
1065
1171
|
onError?.(msg);
|
|
1066
1172
|
}
|
|
1067
|
-
}, [
|
|
1173
|
+
}, [
|
|
1174
|
+
baseUrl,
|
|
1175
|
+
cartId,
|
|
1176
|
+
publishableApiKey,
|
|
1177
|
+
credentials,
|
|
1178
|
+
onPaid,
|
|
1179
|
+
onError,
|
|
1180
|
+
showOverlay,
|
|
1181
|
+
resetSubmitState
|
|
1182
|
+
]);
|
|
1068
1183
|
if (!config.currency_supported) return null;
|
|
1069
1184
|
if (isRejected) {
|
|
1070
|
-
return /* @__PURE__ */
|
|
1071
|
-
"div",
|
|
1072
|
-
{
|
|
1073
|
-
role: "alert",
|
|
1074
|
-
style: {
|
|
1075
|
-
display: "flex",
|
|
1076
|
-
alignItems: "flex-start",
|
|
1077
|
-
gap: 8,
|
|
1078
|
-
padding: "10px 14px",
|
|
1079
|
-
background: "#fef2f2",
|
|
1080
|
-
border: "1px solid #fecaca",
|
|
1081
|
-
borderRadius: 8,
|
|
1082
|
-
fontSize: 13,
|
|
1083
|
-
color: "#b91c1c",
|
|
1084
|
-
lineHeight: 1.5
|
|
1085
|
-
},
|
|
1086
|
-
children: [
|
|
1087
|
-
/* @__PURE__ */ jsx4("span", { style: { flexShrink: 0, fontSize: 15 }, children: "\u26A0\uFE0F" }),
|
|
1088
|
-
/* @__PURE__ */ jsx4("span", { children: "PayPal failed to load. Please refresh the page or try a different payment method." })
|
|
1089
|
-
]
|
|
1090
|
-
}
|
|
1091
|
-
);
|
|
1185
|
+
return /* @__PURE__ */ jsx5(ErrorBanner, { children: "PayPal failed to load. Please refresh the page or try a different payment method." });
|
|
1092
1186
|
}
|
|
1093
1187
|
if (!config.client_token) {
|
|
1094
|
-
return /* @__PURE__ */
|
|
1188
|
+
return /* @__PURE__ */ jsx5(
|
|
1095
1189
|
"div",
|
|
1096
1190
|
{
|
|
1097
1191
|
style: {
|
|
@@ -1108,168 +1202,16 @@ function PayPalAdvancedCard(props) {
|
|
|
1108
1202
|
}
|
|
1109
1203
|
const isSandbox = config.environment === "sandbox";
|
|
1110
1204
|
if (isPending) {
|
|
1111
|
-
return /* @__PURE__ */
|
|
1112
|
-
|
|
1113
|
-
{
|
|
1114
|
-
|
|
1115
|
-
"aria-label": "Loading PayPal",
|
|
1116
|
-
style: {
|
|
1117
|
-
display: "flex",
|
|
1118
|
-
alignItems: "center",
|
|
1119
|
-
justifyContent: "center",
|
|
1120
|
-
gap: 10,
|
|
1121
|
-
padding: "18px 16px",
|
|
1122
|
-
background: "#f9fafb",
|
|
1123
|
-
border: "1px solid #e5e7eb",
|
|
1124
|
-
borderRadius: 8,
|
|
1125
|
-
minHeight: 55
|
|
1126
|
-
},
|
|
1127
|
-
children: [
|
|
1128
|
-
/* @__PURE__ */ jsx4("style", { children: SPIN_STYLE2 }),
|
|
1129
|
-
/* @__PURE__ */ jsx4(
|
|
1130
|
-
"div",
|
|
1131
|
-
{
|
|
1132
|
-
style: {
|
|
1133
|
-
width: 22,
|
|
1134
|
-
height: 22,
|
|
1135
|
-
borderRadius: "50%",
|
|
1136
|
-
border: "2.5px solid #e5e7eb",
|
|
1137
|
-
borderTopColor: "#0070ba",
|
|
1138
|
-
animation: "_pp_spin .7s linear infinite",
|
|
1139
|
-
flexShrink: 0
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
),
|
|
1143
|
-
/* @__PURE__ */ jsx4("div", { style: { fontSize: 13, fontWeight: 500, color: "#6b7280" }, children: "Loading card fields\u2026" })
|
|
1144
|
-
]
|
|
1145
|
-
}
|
|
1146
|
-
);
|
|
1205
|
+
return /* @__PURE__ */ jsxs4("div", { children: [
|
|
1206
|
+
/* @__PURE__ */ jsx5(AnimationStyles, {}),
|
|
1207
|
+
/* @__PURE__ */ jsx5(LoadingCard, { label: "Loading card fields\u2026" })
|
|
1208
|
+
] });
|
|
1147
1209
|
}
|
|
1148
1210
|
if (!isResolved) return null;
|
|
1149
|
-
return /* @__PURE__ */
|
|
1150
|
-
/* @__PURE__ */
|
|
1151
|
-
submitting && /* @__PURE__ */
|
|
1152
|
-
|
|
1153
|
-
{
|
|
1154
|
-
role: "status",
|
|
1155
|
-
"aria-label": "Processing payment",
|
|
1156
|
-
style: {
|
|
1157
|
-
position: "fixed",
|
|
1158
|
-
inset: 0,
|
|
1159
|
-
zIndex: 9999,
|
|
1160
|
-
background: "rgba(255,255,255,0.96)",
|
|
1161
|
-
display: "flex",
|
|
1162
|
-
flexDirection: "column",
|
|
1163
|
-
alignItems: "center",
|
|
1164
|
-
justifyContent: "center",
|
|
1165
|
-
gap: 20
|
|
1166
|
-
},
|
|
1167
|
-
children: [
|
|
1168
|
-
/* @__PURE__ */ jsxs3("div", { style: { position: "relative", width: 56, height: 56 }, children: [
|
|
1169
|
-
/* @__PURE__ */ jsx4(
|
|
1170
|
-
"div",
|
|
1171
|
-
{
|
|
1172
|
-
style: {
|
|
1173
|
-
position: "absolute",
|
|
1174
|
-
inset: 0,
|
|
1175
|
-
borderRadius: "50%",
|
|
1176
|
-
border: "3px solid #e5e7eb"
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
),
|
|
1180
|
-
/* @__PURE__ */ jsx4(
|
|
1181
|
-
"div",
|
|
1182
|
-
{
|
|
1183
|
-
style: {
|
|
1184
|
-
position: "absolute",
|
|
1185
|
-
inset: 0,
|
|
1186
|
-
borderRadius: "50%",
|
|
1187
|
-
border: "3px solid transparent",
|
|
1188
|
-
borderTopColor: "#2563eb",
|
|
1189
|
-
animation: "_pp_spin .8s linear infinite"
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
),
|
|
1193
|
-
/* @__PURE__ */ jsx4(
|
|
1194
|
-
"svg",
|
|
1195
|
-
{
|
|
1196
|
-
viewBox: "0 0 24 24",
|
|
1197
|
-
fill: "none",
|
|
1198
|
-
stroke: "#2563eb",
|
|
1199
|
-
strokeWidth: "1.8",
|
|
1200
|
-
strokeLinecap: "round",
|
|
1201
|
-
strokeLinejoin: "round",
|
|
1202
|
-
style: {
|
|
1203
|
-
position: "absolute",
|
|
1204
|
-
top: "50%",
|
|
1205
|
-
left: "50%",
|
|
1206
|
-
transform: "translate(-50%, -50%)",
|
|
1207
|
-
width: 24,
|
|
1208
|
-
height: 24
|
|
1209
|
-
},
|
|
1210
|
-
children: /* @__PURE__ */ jsx4("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" })
|
|
1211
|
-
}
|
|
1212
|
-
)
|
|
1213
|
-
] }),
|
|
1214
|
-
/* @__PURE__ */ jsxs3("div", { style: { textAlign: "center" }, children: [
|
|
1215
|
-
/* @__PURE__ */ jsx4(
|
|
1216
|
-
"div",
|
|
1217
|
-
{
|
|
1218
|
-
style: {
|
|
1219
|
-
fontSize: 18,
|
|
1220
|
-
fontWeight: 600,
|
|
1221
|
-
color: "#111827",
|
|
1222
|
-
letterSpacing: "-0.01em"
|
|
1223
|
-
},
|
|
1224
|
-
children: "Processing your payment"
|
|
1225
|
-
}
|
|
1226
|
-
),
|
|
1227
|
-
/* @__PURE__ */ jsxs3(
|
|
1228
|
-
"div",
|
|
1229
|
-
{
|
|
1230
|
-
style: {
|
|
1231
|
-
fontSize: 14,
|
|
1232
|
-
color: "#6b7280",
|
|
1233
|
-
marginTop: 6,
|
|
1234
|
-
lineHeight: 1.5
|
|
1235
|
-
},
|
|
1236
|
-
children: [
|
|
1237
|
-
"This may take a few moments. Please do not close",
|
|
1238
|
-
/* @__PURE__ */ jsx4("br", {}),
|
|
1239
|
-
"or refresh this page."
|
|
1240
|
-
]
|
|
1241
|
-
}
|
|
1242
|
-
)
|
|
1243
|
-
] }),
|
|
1244
|
-
/* @__PURE__ */ jsx4(
|
|
1245
|
-
"div",
|
|
1246
|
-
{
|
|
1247
|
-
style: {
|
|
1248
|
-
width: 200,
|
|
1249
|
-
height: 3,
|
|
1250
|
-
background: "#e5e7eb",
|
|
1251
|
-
borderRadius: 3,
|
|
1252
|
-
overflow: "hidden",
|
|
1253
|
-
marginTop: 4
|
|
1254
|
-
},
|
|
1255
|
-
children: /* @__PURE__ */ jsx4(
|
|
1256
|
-
"div",
|
|
1257
|
-
{
|
|
1258
|
-
style: {
|
|
1259
|
-
width: "40%",
|
|
1260
|
-
height: "100%",
|
|
1261
|
-
background: "linear-gradient(90deg, #2563eb, #1d4ed8)",
|
|
1262
|
-
borderRadius: 3,
|
|
1263
|
-
animation: "_pp_progress 1.5s ease-in-out infinite"
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
)
|
|
1267
|
-
}
|
|
1268
|
-
)
|
|
1269
|
-
]
|
|
1270
|
-
}
|
|
1271
|
-
),
|
|
1272
|
-
/* @__PURE__ */ jsx4(
|
|
1211
|
+
return /* @__PURE__ */ jsxs4("div", { style: { position: "relative" }, children: [
|
|
1212
|
+
/* @__PURE__ */ jsx5(AnimationStyles, {}),
|
|
1213
|
+
submitting && !domOverlayUp && /* @__PURE__ */ jsx5(ProcessingOverlayView, { accent: "#2563eb" }),
|
|
1214
|
+
/* @__PURE__ */ jsx5(
|
|
1273
1215
|
PayPalCardFieldsProvider,
|
|
1274
1216
|
{
|
|
1275
1217
|
style: cardStyle,
|
|
@@ -1295,7 +1237,7 @@ function PayPalAdvancedCard(props) {
|
|
|
1295
1237
|
onApprove: async (data) => {
|
|
1296
1238
|
try {
|
|
1297
1239
|
setError(null);
|
|
1298
|
-
|
|
1240
|
+
showOverlay();
|
|
1299
1241
|
const orderId = String(data?.orderID || "");
|
|
1300
1242
|
if (!orderId)
|
|
1301
1243
|
throw new Error(
|
|
@@ -1315,21 +1257,15 @@ function PayPalAdvancedCard(props) {
|
|
|
1315
1257
|
await finalizeCapturedPayment();
|
|
1316
1258
|
},
|
|
1317
1259
|
onCancel: () => {
|
|
1318
|
-
|
|
1319
|
-
creatingOrderRef.current = false;
|
|
1320
|
-
submittingRef.current = false;
|
|
1321
|
-
setSubmitting(false);
|
|
1260
|
+
resetSubmitState();
|
|
1322
1261
|
},
|
|
1323
1262
|
onError: (e) => {
|
|
1324
1263
|
const msg = e instanceof Error ? e.message : e?.message || "CardFields error";
|
|
1325
1264
|
setError(msg);
|
|
1326
1265
|
onError?.(msg);
|
|
1327
|
-
|
|
1328
|
-
creatingOrderRef.current = false;
|
|
1329
|
-
submittingRef.current = false;
|
|
1330
|
-
setSubmitting(false);
|
|
1266
|
+
resetSubmitState();
|
|
1331
1267
|
},
|
|
1332
|
-
children: /* @__PURE__ */
|
|
1268
|
+
children: /* @__PURE__ */ jsxs4(
|
|
1333
1269
|
"div",
|
|
1334
1270
|
{
|
|
1335
1271
|
style: {
|
|
@@ -1339,7 +1275,7 @@ function PayPalAdvancedCard(props) {
|
|
|
1339
1275
|
width: "100%"
|
|
1340
1276
|
},
|
|
1341
1277
|
children: [
|
|
1342
|
-
isSandbox && /* @__PURE__ */
|
|
1278
|
+
isSandbox && /* @__PURE__ */ jsxs4(
|
|
1343
1279
|
"div",
|
|
1344
1280
|
{
|
|
1345
1281
|
style: {
|
|
@@ -1355,11 +1291,18 @@ function PayPalAdvancedCard(props) {
|
|
|
1355
1291
|
lineHeight: 1.55
|
|
1356
1292
|
},
|
|
1357
1293
|
children: [
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
|
|
1294
|
+
/* @__PURE__ */ jsx5(
|
|
1295
|
+
"span",
|
|
1296
|
+
{
|
|
1297
|
+
"aria-hidden": "true",
|
|
1298
|
+
style: { fontSize: 15, flexShrink: 0, marginTop: 1 },
|
|
1299
|
+
children: "\u{1F9EA}"
|
|
1300
|
+
}
|
|
1301
|
+
),
|
|
1302
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1360
1303
|
"Sandbox mode \u2014 use test card",
|
|
1361
1304
|
" ",
|
|
1362
|
-
/* @__PURE__ */
|
|
1305
|
+
/* @__PURE__ */ jsx5(
|
|
1363
1306
|
"strong",
|
|
1364
1307
|
{
|
|
1365
1308
|
style: { fontFamily: "monospace", letterSpacing: "0.05em" },
|
|
@@ -1372,11 +1315,11 @@ function PayPalAdvancedCard(props) {
|
|
|
1372
1315
|
]
|
|
1373
1316
|
}
|
|
1374
1317
|
),
|
|
1375
|
-
/* @__PURE__ */
|
|
1376
|
-
/* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1318
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1319
|
+
/* @__PURE__ */ jsx5("label", { style: labelStyle, id: "_pp-label-card-number", children: "Card number" }),
|
|
1320
|
+
/* @__PURE__ */ jsx5(PayPalNumberField, {})
|
|
1378
1321
|
] }),
|
|
1379
|
-
/* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ jsxs4(
|
|
1380
1323
|
"div",
|
|
1381
1324
|
{
|
|
1382
1325
|
style: {
|
|
@@ -1385,18 +1328,18 @@ function PayPalAdvancedCard(props) {
|
|
|
1385
1328
|
gap: 16
|
|
1386
1329
|
},
|
|
1387
1330
|
children: [
|
|
1388
|
-
/* @__PURE__ */
|
|
1389
|
-
/* @__PURE__ */
|
|
1390
|
-
/* @__PURE__ */
|
|
1331
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1332
|
+
/* @__PURE__ */ jsx5("label", { style: labelStyle, id: "_pp-label-expiry", children: "Expiration date" }),
|
|
1333
|
+
/* @__PURE__ */ jsx5(PayPalExpiryField, {})
|
|
1391
1334
|
] }),
|
|
1392
|
-
/* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1335
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1336
|
+
/* @__PURE__ */ jsx5("label", { style: labelStyle, id: "_pp-label-cvv", children: "Security code" }),
|
|
1337
|
+
/* @__PURE__ */ jsx5(PayPalCVVField, {})
|
|
1395
1338
|
] })
|
|
1396
1339
|
]
|
|
1397
1340
|
}
|
|
1398
1341
|
),
|
|
1399
|
-
/* @__PURE__ */
|
|
1342
|
+
/* @__PURE__ */ jsxs4(
|
|
1400
1343
|
"div",
|
|
1401
1344
|
{
|
|
1402
1345
|
style: {
|
|
@@ -1407,25 +1350,12 @@ function PayPalAdvancedCard(props) {
|
|
|
1407
1350
|
color: "#6b7280"
|
|
1408
1351
|
},
|
|
1409
1352
|
children: [
|
|
1410
|
-
/* @__PURE__ */
|
|
1411
|
-
|
|
1412
|
-
{
|
|
1413
|
-
width: "14",
|
|
1414
|
-
height: "14",
|
|
1415
|
-
viewBox: "0 0 24 24",
|
|
1416
|
-
fill: "none",
|
|
1417
|
-
stroke: "#10b981",
|
|
1418
|
-
strokeWidth: "2.5",
|
|
1419
|
-
strokeLinecap: "round",
|
|
1420
|
-
strokeLinejoin: "round",
|
|
1421
|
-
children: /* @__PURE__ */ jsx4("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" })
|
|
1422
|
-
}
|
|
1423
|
-
),
|
|
1424
|
-
/* @__PURE__ */ jsx4("span", { children: "Your payment is secured with 256-bit SSL encryption" })
|
|
1353
|
+
/* @__PURE__ */ jsx5(ShieldIcon, { color: "#10b981", size: 14 }),
|
|
1354
|
+
/* @__PURE__ */ jsx5("span", { children: "Your payment is secured with 256-bit SSL encryption" })
|
|
1425
1355
|
]
|
|
1426
1356
|
}
|
|
1427
1357
|
),
|
|
1428
|
-
completionPending ? /* @__PURE__ */
|
|
1358
|
+
completionPending ? /* @__PURE__ */ jsx5(
|
|
1429
1359
|
"button",
|
|
1430
1360
|
{
|
|
1431
1361
|
type: "button",
|
|
@@ -1447,17 +1377,18 @@ function PayPalAdvancedCard(props) {
|
|
|
1447
1377
|
},
|
|
1448
1378
|
children: "Retry \u2014 finish placing my order"
|
|
1449
1379
|
}
|
|
1450
|
-
) : /* @__PURE__ */
|
|
1380
|
+
) : /* @__PURE__ */ jsx5(
|
|
1451
1381
|
SubmitButton,
|
|
1452
1382
|
{
|
|
1453
1383
|
disabled: submitting,
|
|
1384
|
+
busy: submitting,
|
|
1454
1385
|
label: submitting ? "Processing\u2026" : "Pay by Card",
|
|
1455
1386
|
onSubmit: () => {
|
|
1456
1387
|
if (submittingRef.current) return;
|
|
1457
1388
|
submittingRef.current = true;
|
|
1458
1389
|
setError(null);
|
|
1459
1390
|
setSubmitting(true);
|
|
1460
|
-
|
|
1391
|
+
showOverlay();
|
|
1461
1392
|
},
|
|
1462
1393
|
onSubmitError: (msg) => {
|
|
1463
1394
|
resetSubmitState();
|
|
@@ -1466,28 +1397,7 @@ function PayPalAdvancedCard(props) {
|
|
|
1466
1397
|
}
|
|
1467
1398
|
}
|
|
1468
1399
|
),
|
|
1469
|
-
error && /* @__PURE__ */
|
|
1470
|
-
"div",
|
|
1471
|
-
{
|
|
1472
|
-
role: "alert",
|
|
1473
|
-
style: {
|
|
1474
|
-
display: "flex",
|
|
1475
|
-
alignItems: "flex-start",
|
|
1476
|
-
gap: 10,
|
|
1477
|
-
padding: "10px 14px",
|
|
1478
|
-
background: "#fef2f2",
|
|
1479
|
-
border: "1px solid #fecaca",
|
|
1480
|
-
borderRadius: 8,
|
|
1481
|
-
fontSize: 13,
|
|
1482
|
-
color: "#b91c1c",
|
|
1483
|
-
lineHeight: 1.5
|
|
1484
|
-
},
|
|
1485
|
-
children: [
|
|
1486
|
-
/* @__PURE__ */ jsx4("span", { style: { flexShrink: 0, marginTop: 1 }, children: "\u26A0\uFE0F" }),
|
|
1487
|
-
/* @__PURE__ */ jsx4("span", { children: error })
|
|
1488
|
-
]
|
|
1489
|
-
}
|
|
1490
|
-
)
|
|
1400
|
+
error && /* @__PURE__ */ jsx5(ErrorBanner, { children: error })
|
|
1491
1401
|
]
|
|
1492
1402
|
}
|
|
1493
1403
|
)
|
|
@@ -1498,28 +1408,12 @@ function PayPalAdvancedCard(props) {
|
|
|
1498
1408
|
|
|
1499
1409
|
// src/adapters/MedusaNextPayPalAdapter.tsx
|
|
1500
1410
|
import { useCallback as useCallback2 } from "react";
|
|
1501
|
-
|
|
1502
|
-
// src/constants.ts
|
|
1503
|
-
var PAYPAL_WALLET_PROVIDER_ID = "pp_paypal_paypal";
|
|
1504
|
-
var PAYPAL_CARD_PROVIDER_ID = "pp_paypal_card_paypal_card";
|
|
1505
|
-
var PAYPAL_PROVIDER_IDS = [
|
|
1506
|
-
PAYPAL_WALLET_PROVIDER_ID,
|
|
1507
|
-
PAYPAL_CARD_PROVIDER_ID
|
|
1508
|
-
];
|
|
1509
|
-
function isPayPalProviderId(providerId) {
|
|
1510
|
-
if (!providerId) return false;
|
|
1511
|
-
return PAYPAL_PROVIDER_IDS.includes(providerId);
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
// src/adapters/MedusaNextPayPalAdapter.tsx
|
|
1515
|
-
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1516
|
-
var SPIN_STYLE3 = `@keyframes _pp_spin { to { transform: rotate(360deg) } }`;
|
|
1411
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1517
1412
|
function PayPalLoadingCard() {
|
|
1518
|
-
return /* @__PURE__ */
|
|
1413
|
+
return /* @__PURE__ */ jsxs5(
|
|
1519
1414
|
"div",
|
|
1520
1415
|
{
|
|
1521
1416
|
role: "status",
|
|
1522
|
-
"aria-label": "Connecting to PayPal",
|
|
1523
1417
|
style: {
|
|
1524
1418
|
display: "flex",
|
|
1525
1419
|
alignItems: "center",
|
|
@@ -1530,31 +1424,35 @@ function PayPalLoadingCard() {
|
|
|
1530
1424
|
borderRadius: 10
|
|
1531
1425
|
},
|
|
1532
1426
|
children: [
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1427
|
+
/* @__PURE__ */ jsx6(AnimationStyles, {}),
|
|
1428
|
+
/* @__PURE__ */ jsx6(
|
|
1535
1429
|
"div",
|
|
1536
1430
|
{
|
|
1431
|
+
className: "_pp-spin-sm",
|
|
1432
|
+
"aria-hidden": "true",
|
|
1537
1433
|
style: {
|
|
1538
1434
|
width: 22,
|
|
1539
1435
|
height: 22,
|
|
1540
1436
|
borderRadius: "50%",
|
|
1541
1437
|
border: "2.5px solid #e5e7eb",
|
|
1542
1438
|
borderTopColor: "#0070ba",
|
|
1543
|
-
animation: "_pp_spin .7s linear infinite",
|
|
1544
1439
|
flexShrink: 0
|
|
1545
1440
|
}
|
|
1546
1441
|
}
|
|
1547
1442
|
),
|
|
1548
|
-
/* @__PURE__ */
|
|
1549
|
-
/* @__PURE__ */
|
|
1550
|
-
/* @__PURE__ */
|
|
1443
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
1444
|
+
/* @__PURE__ */ jsx6("div", { style: { fontSize: 13, fontWeight: 500, color: "#111827" }, children: "Connecting to PayPal\u2026" }),
|
|
1445
|
+
/* @__PURE__ */ jsx6("div", { style: { fontSize: 12, color: "#6b7280", marginTop: 2 }, children: "Setting up secure payment" })
|
|
1551
1446
|
] })
|
|
1552
1447
|
]
|
|
1553
1448
|
}
|
|
1554
1449
|
);
|
|
1555
1450
|
}
|
|
1556
|
-
function PayPalErrorCard({
|
|
1557
|
-
|
|
1451
|
+
function PayPalErrorCard({
|
|
1452
|
+
message,
|
|
1453
|
+
onRetry
|
|
1454
|
+
}) {
|
|
1455
|
+
return /* @__PURE__ */ jsxs5(
|
|
1558
1456
|
"div",
|
|
1559
1457
|
{
|
|
1560
1458
|
role: "alert",
|
|
@@ -1566,12 +1464,34 @@ function PayPalErrorCard({ message }) {
|
|
|
1566
1464
|
fontSize: 13,
|
|
1567
1465
|
color: "#b91c1c"
|
|
1568
1466
|
},
|
|
1569
|
-
children:
|
|
1467
|
+
children: [
|
|
1468
|
+
message,
|
|
1469
|
+
onRetry && /* @__PURE__ */ jsx6(
|
|
1470
|
+
"button",
|
|
1471
|
+
{
|
|
1472
|
+
type: "button",
|
|
1473
|
+
onClick: onRetry,
|
|
1474
|
+
style: {
|
|
1475
|
+
display: "block",
|
|
1476
|
+
marginTop: 8,
|
|
1477
|
+
padding: "6px 14px",
|
|
1478
|
+
background: "#ffffff",
|
|
1479
|
+
color: "#b91c1c",
|
|
1480
|
+
border: "1px solid #fecaca",
|
|
1481
|
+
borderRadius: 6,
|
|
1482
|
+
fontSize: 13,
|
|
1483
|
+
fontWeight: 500,
|
|
1484
|
+
cursor: "pointer"
|
|
1485
|
+
},
|
|
1486
|
+
children: "Try again"
|
|
1487
|
+
}
|
|
1488
|
+
)
|
|
1489
|
+
]
|
|
1570
1490
|
}
|
|
1571
1491
|
);
|
|
1572
1492
|
}
|
|
1573
1493
|
function PayPalUnavailableCard({ label }) {
|
|
1574
|
-
return /* @__PURE__ */
|
|
1494
|
+
return /* @__PURE__ */ jsxs5(
|
|
1575
1495
|
"div",
|
|
1576
1496
|
{
|
|
1577
1497
|
role: "status",
|
|
@@ -1596,6 +1516,8 @@ function MedusaNextPayPalAdapter(props) {
|
|
|
1596
1516
|
selectedProviderId,
|
|
1597
1517
|
baseUrl,
|
|
1598
1518
|
publishableApiKey,
|
|
1519
|
+
credentials,
|
|
1520
|
+
currencyCode,
|
|
1599
1521
|
providerIds,
|
|
1600
1522
|
onSuccess,
|
|
1601
1523
|
onError,
|
|
@@ -1604,10 +1526,12 @@ function MedusaNextPayPalAdapter(props) {
|
|
|
1604
1526
|
const paypalProviderId = providerIds?.paypal || PAYPAL_WALLET_PROVIDER_ID;
|
|
1605
1527
|
const paypalCardProviderId = providerIds?.paypalCard || PAYPAL_CARD_PROVIDER_ID;
|
|
1606
1528
|
const shouldRender = selectedProviderId === paypalProviderId || selectedProviderId === paypalCardProviderId;
|
|
1607
|
-
const { config, loading, error } = usePayPalConfig({
|
|
1529
|
+
const { config, loading, error, retry } = usePayPalConfig({
|
|
1608
1530
|
baseUrl,
|
|
1609
1531
|
publishableApiKey,
|
|
1532
|
+
credentials,
|
|
1610
1533
|
cartId,
|
|
1534
|
+
currencyCode,
|
|
1611
1535
|
enabled: shouldRender
|
|
1612
1536
|
});
|
|
1613
1537
|
const handlePaid = useCallback2(
|
|
@@ -1618,40 +1542,42 @@ function MedusaNextPayPalAdapter(props) {
|
|
|
1618
1542
|
[cartId, onPaid, onSuccess]
|
|
1619
1543
|
);
|
|
1620
1544
|
if (!shouldRender) return null;
|
|
1621
|
-
if (loading) return /* @__PURE__ */
|
|
1622
|
-
if (error) return /* @__PURE__ */
|
|
1545
|
+
if (loading) return /* @__PURE__ */ jsx6(PayPalLoadingCard, {});
|
|
1546
|
+
if (error) return /* @__PURE__ */ jsx6(PayPalErrorCard, { message: error, onRetry: retry });
|
|
1623
1547
|
if (!config) return null;
|
|
1624
1548
|
const isCardProvider = selectedProviderId === paypalCardProviderId;
|
|
1625
1549
|
if (config.paypal_enabled === false && !isCardProvider) {
|
|
1626
|
-
return /* @__PURE__ */
|
|
1550
|
+
return /* @__PURE__ */ jsx6(PayPalUnavailableCard, { label: config.paypal_title || "PayPal" });
|
|
1627
1551
|
}
|
|
1628
1552
|
if (isCardProvider && config.card_enabled === false) {
|
|
1629
|
-
return /* @__PURE__ */
|
|
1553
|
+
return /* @__PURE__ */ jsx6(PayPalUnavailableCard, { label: config.card_title || "Card payment" });
|
|
1630
1554
|
}
|
|
1631
1555
|
const disableFunding = Array.isArray(config.disable_buttons) ? config.disable_buttons.join(",") : void 0;
|
|
1632
|
-
return /* @__PURE__ */
|
|
1633
|
-
/* @__PURE__ */
|
|
1634
|
-
/* @__PURE__ */
|
|
1556
|
+
return /* @__PURE__ */ jsxs5("div", { style: { display: "grid", gap: 12 }, children: [
|
|
1557
|
+
/* @__PURE__ */ jsx6(PayPalCurrencyNotice, { config }),
|
|
1558
|
+
/* @__PURE__ */ jsx6(
|
|
1635
1559
|
PayPalProvider,
|
|
1636
1560
|
{
|
|
1637
1561
|
config,
|
|
1638
1562
|
intent: config.intent === "authorize" ? "authorize" : "capture",
|
|
1639
1563
|
disableFunding,
|
|
1640
|
-
children: isCardProvider ? /* @__PURE__ */
|
|
1564
|
+
children: isCardProvider ? /* @__PURE__ */ jsx6(
|
|
1641
1565
|
PayPalAdvancedCard,
|
|
1642
1566
|
{
|
|
1643
1567
|
baseUrl,
|
|
1644
1568
|
publishableApiKey,
|
|
1569
|
+
credentials,
|
|
1645
1570
|
cartId,
|
|
1646
1571
|
config,
|
|
1647
1572
|
onPaid: handlePaid,
|
|
1648
1573
|
onError
|
|
1649
1574
|
}
|
|
1650
|
-
) : /* @__PURE__ */
|
|
1575
|
+
) : /* @__PURE__ */ jsx6(
|
|
1651
1576
|
PayPalSmartButtons,
|
|
1652
1577
|
{
|
|
1653
1578
|
baseUrl,
|
|
1654
1579
|
publishableApiKey,
|
|
1580
|
+
credentials,
|
|
1655
1581
|
cartId,
|
|
1656
1582
|
config,
|
|
1657
1583
|
onPaid: handlePaid,
|
|
@@ -1664,14 +1590,12 @@ function MedusaNextPayPalAdapter(props) {
|
|
|
1664
1590
|
}
|
|
1665
1591
|
|
|
1666
1592
|
// src/components/PayPalPaymentSection.tsx
|
|
1667
|
-
import { jsx as
|
|
1668
|
-
var SPIN_STYLE4 = `@keyframes _pp_section_spin { to { transform: rotate(360deg) } }`;
|
|
1593
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1669
1594
|
function SessionInitCard() {
|
|
1670
|
-
return /* @__PURE__ */
|
|
1595
|
+
return /* @__PURE__ */ jsxs6(
|
|
1671
1596
|
"div",
|
|
1672
1597
|
{
|
|
1673
1598
|
role: "status",
|
|
1674
|
-
"aria-label": "Setting up payment",
|
|
1675
1599
|
style: {
|
|
1676
1600
|
display: "flex",
|
|
1677
1601
|
alignItems: "center",
|
|
@@ -1683,22 +1607,23 @@ function SessionInitCard() {
|
|
|
1683
1607
|
borderRadius: 10
|
|
1684
1608
|
},
|
|
1685
1609
|
children: [
|
|
1686
|
-
/* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1610
|
+
/* @__PURE__ */ jsx7(AnimationStyles, {}),
|
|
1611
|
+
/* @__PURE__ */ jsx7(
|
|
1688
1612
|
"div",
|
|
1689
1613
|
{
|
|
1614
|
+
className: "_pp-spin-sm",
|
|
1615
|
+
"aria-hidden": "true",
|
|
1690
1616
|
style: {
|
|
1691
1617
|
width: 20,
|
|
1692
1618
|
height: 20,
|
|
1693
1619
|
borderRadius: "50%",
|
|
1694
1620
|
border: "2.5px solid #e5e7eb",
|
|
1695
1621
|
borderTopColor: "#0070ba",
|
|
1696
|
-
animation: "_pp_section_spin .7s linear infinite",
|
|
1697
1622
|
flexShrink: 0
|
|
1698
1623
|
}
|
|
1699
1624
|
}
|
|
1700
1625
|
),
|
|
1701
|
-
/* @__PURE__ */
|
|
1626
|
+
/* @__PURE__ */ jsx7("div", { style: { fontSize: 13, fontWeight: 500, color: "#111827" }, children: "Setting up payment\u2026" })
|
|
1702
1627
|
]
|
|
1703
1628
|
}
|
|
1704
1629
|
);
|
|
@@ -1708,20 +1633,24 @@ function PayPalPaymentSection({
|
|
|
1708
1633
|
selectedProviderId,
|
|
1709
1634
|
baseUrl,
|
|
1710
1635
|
publishableApiKey,
|
|
1636
|
+
credentials,
|
|
1637
|
+
currencyCode,
|
|
1711
1638
|
sessionLoading = false,
|
|
1712
1639
|
onSuccess,
|
|
1713
1640
|
onError,
|
|
1714
1641
|
onPaid
|
|
1715
1642
|
}) {
|
|
1716
1643
|
if (!isPayPalProviderId(selectedProviderId)) return null;
|
|
1717
|
-
if (sessionLoading) return /* @__PURE__ */
|
|
1718
|
-
return /* @__PURE__ */
|
|
1644
|
+
if (sessionLoading) return /* @__PURE__ */ jsx7(SessionInitCard, {});
|
|
1645
|
+
return /* @__PURE__ */ jsx7(
|
|
1719
1646
|
MedusaNextPayPalAdapter,
|
|
1720
1647
|
{
|
|
1721
1648
|
cartId,
|
|
1722
1649
|
selectedProviderId,
|
|
1723
1650
|
baseUrl,
|
|
1724
1651
|
publishableApiKey,
|
|
1652
|
+
credentials,
|
|
1653
|
+
currencyCode,
|
|
1725
1654
|
onSuccess,
|
|
1726
1655
|
onError,
|
|
1727
1656
|
onPaid
|
|
@@ -1731,19 +1660,6 @@ function PayPalPaymentSection({
|
|
|
1731
1660
|
|
|
1732
1661
|
// src/hooks/usePayPalPaymentMethods.ts
|
|
1733
1662
|
import { useEffect as useEffect3, useMemo as useMemo5, useRef as useRef4, useState as useState4 } from "react";
|
|
1734
|
-
var MAX_CACHE_ENTRIES2 = 50;
|
|
1735
|
-
var _cache2 = /* @__PURE__ */ new Map();
|
|
1736
|
-
var CACHE_TTL2 = 5 * 60 * 1e3;
|
|
1737
|
-
function cacheSet2(key, value) {
|
|
1738
|
-
if (_cache2.size >= MAX_CACHE_ENTRIES2) {
|
|
1739
|
-
const oldest = _cache2.keys().next().value;
|
|
1740
|
-
if (oldest !== void 0) _cache2.delete(oldest);
|
|
1741
|
-
}
|
|
1742
|
-
_cache2.set(key, value);
|
|
1743
|
-
}
|
|
1744
|
-
function cacheKey2(baseUrl, cartId) {
|
|
1745
|
-
return `ppm::${baseUrl}::${cartId ?? ""}`;
|
|
1746
|
-
}
|
|
1747
1663
|
var DEFAULT_RESULT = {
|
|
1748
1664
|
paypalEnabled: true,
|
|
1749
1665
|
paypalTitle: "PayPal",
|
|
@@ -1752,21 +1668,37 @@ var DEFAULT_RESULT = {
|
|
|
1752
1668
|
loading: false,
|
|
1753
1669
|
error: null
|
|
1754
1670
|
};
|
|
1671
|
+
function toResult(cfg) {
|
|
1672
|
+
return {
|
|
1673
|
+
paypalEnabled: cfg.paypal_enabled !== false,
|
|
1674
|
+
paypalTitle: typeof cfg.paypal_title === "string" && cfg.paypal_title ? cfg.paypal_title : "PayPal",
|
|
1675
|
+
cardEnabled: cfg.card_enabled !== false,
|
|
1676
|
+
cardTitle: typeof cfg.card_title === "string" && cfg.card_title ? cfg.card_title : "Credit or Debit Card",
|
|
1677
|
+
loading: false,
|
|
1678
|
+
error: null
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1755
1681
|
function usePayPalPaymentMethods({
|
|
1756
1682
|
baseUrl,
|
|
1757
1683
|
publishableApiKey,
|
|
1758
1684
|
cartId,
|
|
1685
|
+
currencyCode,
|
|
1686
|
+
credentials,
|
|
1759
1687
|
enabled = true
|
|
1760
1688
|
}) {
|
|
1761
1689
|
const api = useMemo5(
|
|
1762
|
-
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
1763
|
-
[baseUrl, publishableApiKey]
|
|
1690
|
+
() => createPayPalStoreApi({ baseUrl, publishableApiKey, credentials }),
|
|
1691
|
+
[baseUrl, publishableApiKey, credentials]
|
|
1764
1692
|
);
|
|
1765
|
-
const key =
|
|
1766
|
-
|
|
1767
|
-
|
|
1693
|
+
const key = configCacheKey({
|
|
1694
|
+
baseUrl,
|
|
1695
|
+
publishableApiKey,
|
|
1696
|
+
cartId,
|
|
1697
|
+
currencyCode
|
|
1698
|
+
});
|
|
1699
|
+
const seed = getCachedPayPalConfig(key);
|
|
1768
1700
|
const [result, setResult] = useState4(
|
|
1769
|
-
seed
|
|
1701
|
+
seed ? toResult(seed) : { ...DEFAULT_RESULT, loading: enabled }
|
|
1770
1702
|
);
|
|
1771
1703
|
const fetchIdRef = useRef4(0);
|
|
1772
1704
|
useEffect3(() => {
|
|
@@ -1774,43 +1706,33 @@ function usePayPalPaymentMethods({
|
|
|
1774
1706
|
setResult((prev) => ({ ...prev, loading: false }));
|
|
1775
1707
|
return;
|
|
1776
1708
|
}
|
|
1777
|
-
const
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
setResult(cached.result);
|
|
1709
|
+
const cached = getCachedPayPalConfig(key);
|
|
1710
|
+
if (cached) {
|
|
1711
|
+
setResult(toResult(cached));
|
|
1781
1712
|
return;
|
|
1782
1713
|
}
|
|
1783
1714
|
const id = ++fetchIdRef.current;
|
|
1784
1715
|
let mounted = true;
|
|
1785
|
-
const controller = new AbortController();
|
|
1786
1716
|
setResult((prev) => ({ ...prev, loading: true }));
|
|
1787
1717
|
(async () => {
|
|
1788
1718
|
try {
|
|
1789
|
-
const cfg = await
|
|
1719
|
+
const cfg = await fetchPayPalConfigShared(
|
|
1720
|
+
key,
|
|
1721
|
+
() => api.getConfig(cartId)
|
|
1722
|
+
);
|
|
1790
1723
|
if (!mounted || id !== fetchIdRef.current) return;
|
|
1791
|
-
|
|
1792
|
-
paypalEnabled: cfg.paypal_enabled !== false,
|
|
1793
|
-
paypalTitle: typeof cfg.paypal_title === "string" && cfg.paypal_title ? cfg.paypal_title : "PayPal",
|
|
1794
|
-
cardEnabled: cfg.card_enabled !== false,
|
|
1795
|
-
cardTitle: typeof cfg.card_title === "string" && cfg.card_title ? cfg.card_title : "Credit or Debit Card",
|
|
1796
|
-
loading: false,
|
|
1797
|
-
error: null
|
|
1798
|
-
};
|
|
1799
|
-
cacheSet2(k, { result: next, at: Date.now() });
|
|
1800
|
-
setResult(next);
|
|
1724
|
+
setResult(toResult(cfg));
|
|
1801
1725
|
} catch (e) {
|
|
1802
|
-
const msg = e instanceof Error ? e.message : "";
|
|
1803
|
-
if (e instanceof Error && e.name === "AbortError") return;
|
|
1804
1726
|
if (!mounted || id !== fetchIdRef.current) return;
|
|
1805
|
-
|
|
1806
|
-
|
|
1727
|
+
const msg = e instanceof Error ? e.message : "";
|
|
1728
|
+
if (e instanceof HttpError && e.status === 403) {
|
|
1729
|
+
setResult({
|
|
1807
1730
|
...DEFAULT_RESULT,
|
|
1808
1731
|
paypalEnabled: false,
|
|
1809
1732
|
cardEnabled: false,
|
|
1810
1733
|
loading: false,
|
|
1811
1734
|
error: msg || "PayPal is disabled"
|
|
1812
|
-
};
|
|
1813
|
-
setResult(disabled);
|
|
1735
|
+
});
|
|
1814
1736
|
return;
|
|
1815
1737
|
}
|
|
1816
1738
|
setResult({
|
|
@@ -1822,14 +1744,15 @@ function usePayPalPaymentMethods({
|
|
|
1822
1744
|
})();
|
|
1823
1745
|
return () => {
|
|
1824
1746
|
mounted = false;
|
|
1825
|
-
controller.abort();
|
|
1826
1747
|
};
|
|
1827
|
-
}, [api,
|
|
1748
|
+
}, [api, key, cartId, enabled]);
|
|
1828
1749
|
return result;
|
|
1829
1750
|
}
|
|
1830
1751
|
export {
|
|
1752
|
+
HttpError,
|
|
1831
1753
|
MedusaNextPayPalAdapter,
|
|
1832
1754
|
PAYPAL_CARD_PROVIDER_ID,
|
|
1755
|
+
PAYPAL_PROVIDER_IDS,
|
|
1833
1756
|
PAYPAL_WALLET_PROVIDER_ID,
|
|
1834
1757
|
PayPalAdvancedCard,
|
|
1835
1758
|
PayPalCurrencyNotice,
|
|
@@ -1837,9 +1760,11 @@ export {
|
|
|
1837
1760
|
PayPalProvider,
|
|
1838
1761
|
PayPalSmartButtons,
|
|
1839
1762
|
clearCartCaptured,
|
|
1763
|
+
createHttpClient,
|
|
1840
1764
|
createPayPalStoreApi,
|
|
1841
1765
|
generateIdempotencyKey,
|
|
1842
1766
|
hideProcessingOverlay,
|
|
1767
|
+
invalidatePayPalConfigCache,
|
|
1843
1768
|
isPayPalProviderId,
|
|
1844
1769
|
markCartCaptured,
|
|
1845
1770
|
markPaymentComplete,
|