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