@appfunnel-dev/sdk 0.7.0 → 0.9.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/README.md +2 -80
- package/dist/elements/index.cjs +49 -4
- package/dist/elements/index.cjs.map +1 -1
- package/dist/elements/index.d.cts +19 -1
- package/dist/elements/index.d.ts +19 -1
- package/dist/elements/index.js +49 -5
- package/dist/elements/index.js.map +1 -1
- package/dist/index.cjs +759 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -7
- package/dist/index.d.ts +18 -7
- package/dist/index.js +761 -59
- package/dist/index.js.map +1 -1
- package/dist/{internal-C7seLJBr.d.cts → internal-C9MOEdND.d.cts} +11 -12
- package/dist/{internal-C7seLJBr.d.ts → internal-C9MOEdND.d.ts} +11 -12
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,10 +2,10 @@ import { useNavigation, useResponses } from './chunk-P4SLDMWY.js';
|
|
|
2
2
|
export { useNavigation, useResponse, useResponses } from './chunk-P4SLDMWY.js';
|
|
3
3
|
import { useFunnelContext } from './chunk-H3KHXZSI.js';
|
|
4
4
|
export { FunnelProvider, registerIntegration } from './chunk-H3KHXZSI.js';
|
|
5
|
-
import { forwardRef,
|
|
5
|
+
import { forwardRef, useMemo, useRef, useEffect, useCallback, useImperativeHandle, useState, useSyncExternalStore } from 'react';
|
|
6
6
|
import { loadStripe } from '@stripe/stripe-js';
|
|
7
7
|
import { useStripe, useElements, PaymentElement, EmbeddedCheckoutProvider, EmbeddedCheckout, Elements } from '@stripe/react-stripe-js';
|
|
8
|
-
import {
|
|
8
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
9
|
|
|
10
10
|
// src/config.ts
|
|
11
11
|
function defineConfig(config) {
|
|
@@ -140,7 +140,7 @@ function toISODateWithFormat(input, format) {
|
|
|
140
140
|
|
|
141
141
|
// src/hooks/useUser.ts
|
|
142
142
|
function useUser() {
|
|
143
|
-
const { variableStore } = useFunnelContext();
|
|
143
|
+
const { variableStore, tracker } = useFunnelContext();
|
|
144
144
|
const subscribe = useCallback(
|
|
145
145
|
(cb) => variableStore.subscribe(cb, { prefix: "user." }),
|
|
146
146
|
[variableStore]
|
|
@@ -157,6 +157,7 @@ function useUser() {
|
|
|
157
157
|
stripeCustomerId: variables["user.stripeCustomerId"] || "",
|
|
158
158
|
paddleCustomerId: variables["user.paddleCustomerId"] || "",
|
|
159
159
|
dateOfBirth: variables["user.dateOfBirth"] || "",
|
|
160
|
+
marketingConsent: variables["user.marketingConsent"] === true,
|
|
160
161
|
setEmail(email) {
|
|
161
162
|
variableStore.set("user.email", email);
|
|
162
163
|
},
|
|
@@ -165,9 +166,15 @@ function useUser() {
|
|
|
165
166
|
},
|
|
166
167
|
setDateOfBirth(dateOfBirth) {
|
|
167
168
|
variableStore.set("user.dateOfBirth", toISODate(dateOfBirth));
|
|
169
|
+
},
|
|
170
|
+
setMarketingConsent(consent) {
|
|
171
|
+
variableStore.set("user.marketingConsent", consent);
|
|
172
|
+
},
|
|
173
|
+
identify(email) {
|
|
174
|
+
tracker.identify(email);
|
|
168
175
|
}
|
|
169
176
|
}),
|
|
170
|
-
[variables, variableStore]
|
|
177
|
+
[variables, variableStore, tracker]
|
|
171
178
|
);
|
|
172
179
|
}
|
|
173
180
|
function useUserProperty(field) {
|
|
@@ -341,25 +348,12 @@ function useTracking() {
|
|
|
341
348
|
},
|
|
342
349
|
[tracker]
|
|
343
350
|
);
|
|
344
|
-
|
|
345
|
-
(email) => {
|
|
346
|
-
tracker.identify(email);
|
|
347
|
-
},
|
|
348
|
-
[tracker]
|
|
349
|
-
);
|
|
350
|
-
return { track, identify };
|
|
351
|
+
return { track };
|
|
351
352
|
}
|
|
352
|
-
var
|
|
353
|
-
|
|
354
|
-
"card.brand",
|
|
355
|
-
"card.expMonth",
|
|
356
|
-
"card.expYear",
|
|
357
|
-
"payment.loading",
|
|
358
|
-
"payment.error",
|
|
359
|
-
"payment.customerId"
|
|
360
|
-
];
|
|
353
|
+
var API_BASE_URL = "https://api.appfunnel.net";
|
|
354
|
+
var PAYMENT_KEYS = ["payment.loading", "payment.error"];
|
|
361
355
|
function usePayment() {
|
|
362
|
-
const { variableStore } = useFunnelContext();
|
|
356
|
+
const { variableStore, products, campaignId, tracker } = useFunnelContext();
|
|
363
357
|
const subscribe = useCallback(
|
|
364
358
|
(cb) => variableStore.subscribe(cb, { keys: PAYMENT_KEYS }),
|
|
365
359
|
[variableStore]
|
|
@@ -369,20 +363,258 @@ function usePayment() {
|
|
|
369
363
|
[variableStore]
|
|
370
364
|
);
|
|
371
365
|
const variables = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
366
|
+
const purchase = useCallback(
|
|
367
|
+
async (productId, options) => {
|
|
368
|
+
console.log("[Purchase] Starting purchase for product:", productId);
|
|
369
|
+
if (globalThis.__APPFUNNEL_DEV__) {
|
|
370
|
+
console.log(
|
|
371
|
+
"[Purchase] Dev mode \u2014 simulating success (500ms delay)"
|
|
372
|
+
);
|
|
373
|
+
variableStore.set("payment.loading", true);
|
|
374
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
375
|
+
variableStore.set("payment.error", "");
|
|
376
|
+
console.log("[Purchase] Dev mode \u2014 success");
|
|
377
|
+
options?.onSuccess?.();
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
const customerId = variableStore.get(
|
|
381
|
+
"user.stripeCustomerId"
|
|
382
|
+
);
|
|
383
|
+
console.log("[Purchase] Customer ID:", customerId || "(none)");
|
|
384
|
+
if (!customerId) {
|
|
385
|
+
const msg = "Please complete payment authorization first";
|
|
386
|
+
console.error("[Purchase] Failed:", msg);
|
|
387
|
+
variableStore.set("payment.error", msg);
|
|
388
|
+
options?.onError?.(msg);
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
const product = products.find((p) => p.id === productId);
|
|
392
|
+
console.log(
|
|
393
|
+
"[Purchase] Product found:",
|
|
394
|
+
product ? {
|
|
395
|
+
id: product.id,
|
|
396
|
+
name: product.name,
|
|
397
|
+
stripePriceId: product.stripePriceId
|
|
398
|
+
} : "(not found)"
|
|
399
|
+
);
|
|
400
|
+
if (!product?.stripePriceId) {
|
|
401
|
+
const msg = "Product not found or missing Stripe price";
|
|
402
|
+
console.error("[Purchase] Failed:", msg);
|
|
403
|
+
variableStore.set("payment.error", msg);
|
|
404
|
+
options?.onError?.(msg);
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
const trialPeriodDays = product.hasTrial ? product.trialDays : void 0;
|
|
408
|
+
const trialChargePriceId = product.paidTrial && product.trialStorePriceId ? product.trialStorePriceId : void 0;
|
|
409
|
+
console.log("[Purchase] Trial config:", {
|
|
410
|
+
trialPeriodDays,
|
|
411
|
+
trialChargePriceId,
|
|
412
|
+
hasTrial: product.hasTrial,
|
|
413
|
+
paidTrial: product.paidTrial
|
|
414
|
+
});
|
|
415
|
+
variableStore.set("payment.loading", true);
|
|
416
|
+
variableStore.set("payment.error", "");
|
|
417
|
+
const requestBody = {
|
|
418
|
+
campaignId,
|
|
419
|
+
sessionId: tracker.getSessionId(),
|
|
420
|
+
stripePriceId: product.stripePriceId,
|
|
421
|
+
trialPeriodDays,
|
|
422
|
+
trialChargePriceId
|
|
423
|
+
};
|
|
424
|
+
console.log(
|
|
425
|
+
"[Purchase] Sending request:",
|
|
426
|
+
`${API_BASE_URL}/campaign/${campaignId}/stripe/purchase`,
|
|
427
|
+
requestBody
|
|
428
|
+
);
|
|
429
|
+
try {
|
|
430
|
+
const response = await fetch(
|
|
431
|
+
`${API_BASE_URL}/campaign/${campaignId}/stripe/purchase`,
|
|
432
|
+
{
|
|
433
|
+
method: "POST",
|
|
434
|
+
headers: { "Content-Type": "application/json" },
|
|
435
|
+
body: JSON.stringify(requestBody)
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
console.log("[Purchase] Response status:", response.status);
|
|
439
|
+
let result = await response.json();
|
|
440
|
+
console.log("[Purchase] Response body:", result);
|
|
441
|
+
if (!result.success && result.requiresAction) {
|
|
442
|
+
console.log(
|
|
443
|
+
"[Purchase] 3DS authentication required, loading Stripe..."
|
|
444
|
+
);
|
|
445
|
+
const { loadStripe: loadStripe2 } = await import('@stripe/stripe-js');
|
|
446
|
+
const stripeInstance = await loadStripe2(
|
|
447
|
+
result.publishableKey
|
|
448
|
+
);
|
|
449
|
+
if (!stripeInstance) {
|
|
450
|
+
const msg = "Failed to load payment processor";
|
|
451
|
+
console.error("[Purchase] Failed:", msg);
|
|
452
|
+
variableStore.set("payment.error", msg);
|
|
453
|
+
options?.onError?.(msg);
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
console.log(
|
|
457
|
+
"[Purchase] Confirming card payment with 3DS..."
|
|
458
|
+
);
|
|
459
|
+
const { error: confirmError, paymentIntent: confirmedPi } = await stripeInstance.confirmCardPayment(
|
|
460
|
+
result.clientSecret,
|
|
461
|
+
{
|
|
462
|
+
payment_method: result.paymentMethodId
|
|
463
|
+
}
|
|
464
|
+
);
|
|
465
|
+
if (confirmError || !confirmedPi || confirmedPi.status !== "succeeded") {
|
|
466
|
+
const msg = confirmError?.message || "Payment authentication failed";
|
|
467
|
+
console.error("[Purchase] 3DS failed:", msg);
|
|
468
|
+
variableStore.set("payment.error", msg);
|
|
469
|
+
options?.onError?.(msg);
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
console.log(
|
|
473
|
+
"[Purchase] 3DS succeeded, retrying purchase with confirmed PI:",
|
|
474
|
+
confirmedPi.id
|
|
475
|
+
);
|
|
476
|
+
const retryResponse = await fetch(
|
|
477
|
+
`${API_BASE_URL}/campaign/${campaignId}/stripe/purchase`,
|
|
478
|
+
{
|
|
479
|
+
method: "POST",
|
|
480
|
+
headers: { "Content-Type": "application/json" },
|
|
481
|
+
body: JSON.stringify({
|
|
482
|
+
campaignId,
|
|
483
|
+
sessionId: tracker.getSessionId(),
|
|
484
|
+
stripePriceId: product.stripePriceId,
|
|
485
|
+
trialPeriodDays,
|
|
486
|
+
trialChargePriceId,
|
|
487
|
+
onSessionPiId: confirmedPi.id
|
|
488
|
+
})
|
|
489
|
+
}
|
|
490
|
+
);
|
|
491
|
+
result = await retryResponse.json();
|
|
492
|
+
console.log("[Purchase] Retry response:", result);
|
|
493
|
+
}
|
|
494
|
+
if (result.success) {
|
|
495
|
+
console.log("[Purchase] Success! Type:", result.type);
|
|
496
|
+
variableStore.set("payment.error", "");
|
|
497
|
+
if (result.type === "validate_only") {
|
|
498
|
+
console.log(
|
|
499
|
+
"[Purchase] Validate-only \u2014 setting card variables"
|
|
500
|
+
);
|
|
501
|
+
if (result.card) {
|
|
502
|
+
variableStore.setMany({
|
|
503
|
+
"card.last4": result.card.last4,
|
|
504
|
+
"card.brand": result.card.brand,
|
|
505
|
+
"card.expMonth": result.card.expMonth,
|
|
506
|
+
"card.expYear": result.card.expYear,
|
|
507
|
+
"card.funding": result.card.funding
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
if (result.eventId) {
|
|
511
|
+
console.log(
|
|
512
|
+
"[Purchase] Tracking purchase.complete (validate_only), eventId:",
|
|
513
|
+
result.eventId
|
|
514
|
+
);
|
|
515
|
+
tracker.track("purchase.complete", {
|
|
516
|
+
eventId: result.eventId,
|
|
517
|
+
amount: product.rawPrice ? product.rawPrice / 100 : 0,
|
|
518
|
+
currency: product.currencyCode || "USD"
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
} else if (result.type === "one_time") {
|
|
522
|
+
console.log(
|
|
523
|
+
"[Purchase] One-time charge \u2014 paymentIntentId:",
|
|
524
|
+
result.paymentIntentId
|
|
525
|
+
);
|
|
526
|
+
variableStore.set(
|
|
527
|
+
"stripe.paymentIntentId",
|
|
528
|
+
result.paymentIntentId
|
|
529
|
+
);
|
|
530
|
+
variableStore.set("payment.status", result.status);
|
|
531
|
+
if (result.eventId) {
|
|
532
|
+
console.log(
|
|
533
|
+
"[Purchase] Tracking purchase.complete (one_time), eventId:",
|
|
534
|
+
result.eventId
|
|
535
|
+
);
|
|
536
|
+
tracker.track("purchase.complete", {
|
|
537
|
+
eventId: result.eventId,
|
|
538
|
+
amount: product.rawPrice ? product.rawPrice / 100 : 0,
|
|
539
|
+
currency: product.currencyCode || "USD"
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
} else {
|
|
543
|
+
console.log(
|
|
544
|
+
"[Purchase] Subscription \u2014 subscriptionId:",
|
|
545
|
+
result.subscriptionId,
|
|
546
|
+
"status:",
|
|
547
|
+
result.status
|
|
548
|
+
);
|
|
549
|
+
variableStore.set(
|
|
550
|
+
"stripe.subscriptionId",
|
|
551
|
+
result.subscriptionId
|
|
552
|
+
);
|
|
553
|
+
variableStore.set("subscription.status", result.status);
|
|
554
|
+
if (result.trialCharge) {
|
|
555
|
+
console.log(
|
|
556
|
+
"[Purchase] Tracking trial charge purchase.complete"
|
|
557
|
+
);
|
|
558
|
+
tracker.track("purchase.complete", {
|
|
559
|
+
eventId: result.eventIds?.trialCharge,
|
|
560
|
+
amount: result.trialCharge.amount / 100,
|
|
561
|
+
currency: "USD"
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
if (result.eventIds?.subscription) {
|
|
565
|
+
console.log(
|
|
566
|
+
"[Purchase] Tracking subscription.created, eventId:",
|
|
567
|
+
result.eventIds.subscription
|
|
568
|
+
);
|
|
569
|
+
tracker.track("subscription.created", {
|
|
570
|
+
eventId: result.eventIds.subscription,
|
|
571
|
+
subscriptionId: result.subscriptionId,
|
|
572
|
+
status: result.status
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
if (result.eventIds?.firstPeriod) {
|
|
576
|
+
console.log(
|
|
577
|
+
"[Purchase] Tracking first-period purchase.complete, eventId:",
|
|
578
|
+
result.eventIds.firstPeriod
|
|
579
|
+
);
|
|
580
|
+
tracker.track("purchase.complete", {
|
|
581
|
+
eventId: result.eventIds.firstPeriod,
|
|
582
|
+
amount: product.rawPrice ? product.rawPrice / 100 : 0,
|
|
583
|
+
currency: product.currencyCode || "USD"
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
console.log("[Purchase] Calling onSuccess callback");
|
|
588
|
+
options?.onSuccess?.();
|
|
589
|
+
return true;
|
|
590
|
+
} else {
|
|
591
|
+
const msg = result.error || "Purchase failed";
|
|
592
|
+
console.error("[Purchase] Failed:", msg);
|
|
593
|
+
variableStore.set("payment.error", msg);
|
|
594
|
+
options?.onError?.(msg);
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
} catch (err) {
|
|
598
|
+
const msg = err instanceof Error ? err.message : "Purchase failed";
|
|
599
|
+
console.error("[Purchase] Exception:", err);
|
|
600
|
+
variableStore.set("payment.error", msg);
|
|
601
|
+
options?.onError?.(msg);
|
|
602
|
+
return false;
|
|
603
|
+
} finally {
|
|
604
|
+
console.log("[Purchase] Done \u2014 setting loading to false");
|
|
605
|
+
variableStore.set("payment.loading", false);
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
[variableStore, products, campaignId, tracker]
|
|
609
|
+
);
|
|
610
|
+
return useMemo(
|
|
611
|
+
() => ({
|
|
381
612
|
loading: !!variables["payment.loading"],
|
|
382
613
|
error: variables["payment.error"] || null,
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
|
|
614
|
+
purchase
|
|
615
|
+
}),
|
|
616
|
+
[variables, purchase]
|
|
617
|
+
);
|
|
386
618
|
}
|
|
387
619
|
var DEVICE_KEYS = [
|
|
388
620
|
"os.name",
|
|
@@ -575,7 +807,456 @@ function useFunnel() {
|
|
|
575
807
|
payment: usePayment()
|
|
576
808
|
};
|
|
577
809
|
}
|
|
578
|
-
var
|
|
810
|
+
var FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
811
|
+
var inputStyle = (focused) => ({
|
|
812
|
+
width: "100%",
|
|
813
|
+
padding: "12px",
|
|
814
|
+
border: `1px solid ${focused ? "#666" : "#e0e0e0"}`,
|
|
815
|
+
borderRadius: "6px",
|
|
816
|
+
fontSize: "14px",
|
|
817
|
+
fontFamily: FONT,
|
|
818
|
+
outline: "none",
|
|
819
|
+
backgroundColor: "#fff",
|
|
820
|
+
boxSizing: "border-box",
|
|
821
|
+
transition: "border-color 0.15s"
|
|
822
|
+
});
|
|
823
|
+
var labelStyle = {
|
|
824
|
+
display: "block",
|
|
825
|
+
fontSize: "14px",
|
|
826
|
+
fontWeight: 500,
|
|
827
|
+
color: "#333",
|
|
828
|
+
marginBottom: "6px",
|
|
829
|
+
fontFamily: FONT
|
|
830
|
+
};
|
|
831
|
+
function CardBrandBadges() {
|
|
832
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "4px", alignItems: "center" }, children: [
|
|
833
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontWeight: 700, color: "#1a1f71", background: "#fff", border: "1px solid #e0e0e0", borderRadius: "3px", padding: "2px 4px", fontFamily: FONT }, children: "VISA" }),
|
|
834
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontWeight: 700, color: "#eb001b", background: "#fff", border: "1px solid #e0e0e0", borderRadius: "3px", padding: "2px 4px", fontFamily: FONT }, children: "MC" }),
|
|
835
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontWeight: 700, color: "#ff6000", background: "#fff", border: "1px solid #e0e0e0", borderRadius: "3px", padding: "2px 4px", fontFamily: FONT }, children: "DISC" })
|
|
836
|
+
] });
|
|
837
|
+
}
|
|
838
|
+
function CvcIcon() {
|
|
839
|
+
return /* @__PURE__ */ jsxs("svg", { width: "20", height: "16", viewBox: "0 0 20 16", fill: "none", style: { opacity: 0.4 }, children: [
|
|
840
|
+
/* @__PURE__ */ jsx("rect", { x: "0.5", y: "0.5", width: "19", height: "15", rx: "2", stroke: "#888" }),
|
|
841
|
+
/* @__PURE__ */ jsx("rect", { x: "0", y: "4", width: "20", height: "3", fill: "#888" }),
|
|
842
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "10", width: "8", height: "2", rx: "1", fill: "#ccc" }),
|
|
843
|
+
/* @__PURE__ */ jsx("text", { x: "14", y: "12", fontSize: "6", fill: "#888", fontFamily: FONT, children: "123" })
|
|
844
|
+
] });
|
|
845
|
+
}
|
|
846
|
+
function DemoElementsForm({ onReady }) {
|
|
847
|
+
const [cardNumber, setCardNumber] = useState("");
|
|
848
|
+
const [expiry, setExpiry] = useState("");
|
|
849
|
+
const [cvc, setCvc] = useState("");
|
|
850
|
+
const [country, setCountry] = useState("Denmark");
|
|
851
|
+
const [focusedField, setFocusedField] = useState(null);
|
|
852
|
+
const readyFired = useRef(false);
|
|
853
|
+
useEffect(() => {
|
|
854
|
+
if (!readyFired.current) {
|
|
855
|
+
readyFired.current = true;
|
|
856
|
+
onReady?.();
|
|
857
|
+
}
|
|
858
|
+
}, [onReady]);
|
|
859
|
+
const formatCardNumber = (val) => {
|
|
860
|
+
const digits = val.replace(/\D/g, "").slice(0, 16);
|
|
861
|
+
return digits.replace(/(.{4})/g, "$1 ").trim();
|
|
862
|
+
};
|
|
863
|
+
const formatExpiry = (val) => {
|
|
864
|
+
const digits = val.replace(/\D/g, "").slice(0, 4);
|
|
865
|
+
if (digits.length > 2) return digits.slice(0, 2) + " / " + digits.slice(2);
|
|
866
|
+
return digits;
|
|
867
|
+
};
|
|
868
|
+
return /* @__PURE__ */ jsxs("div", { style: { fontFamily: FONT }, children: [
|
|
869
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "14px" }, children: [
|
|
870
|
+
/* @__PURE__ */ jsx("label", { style: labelStyle, children: "Card number" }),
|
|
871
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
872
|
+
/* @__PURE__ */ jsx(
|
|
873
|
+
"input",
|
|
874
|
+
{
|
|
875
|
+
type: "text",
|
|
876
|
+
value: cardNumber,
|
|
877
|
+
onChange: (e) => setCardNumber(formatCardNumber(e.target.value)),
|
|
878
|
+
onFocus: () => setFocusedField("card"),
|
|
879
|
+
onBlur: () => setFocusedField(null),
|
|
880
|
+
placeholder: "1234 1234 1234 1234",
|
|
881
|
+
style: inputStyle(focusedField === "card")
|
|
882
|
+
}
|
|
883
|
+
),
|
|
884
|
+
/* @__PURE__ */ jsx("div", { style: { position: "absolute", right: "12px", top: "50%", transform: "translateY(-50%)" }, children: /* @__PURE__ */ jsx(CardBrandBadges, {}) })
|
|
885
|
+
] })
|
|
886
|
+
] }),
|
|
887
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px", marginBottom: "14px" }, children: [
|
|
888
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
889
|
+
/* @__PURE__ */ jsx("label", { style: labelStyle, children: "Expiry date" }),
|
|
890
|
+
/* @__PURE__ */ jsx(
|
|
891
|
+
"input",
|
|
892
|
+
{
|
|
893
|
+
type: "text",
|
|
894
|
+
value: expiry,
|
|
895
|
+
onChange: (e) => setExpiry(formatExpiry(e.target.value)),
|
|
896
|
+
onFocus: () => setFocusedField("expiry"),
|
|
897
|
+
onBlur: () => setFocusedField(null),
|
|
898
|
+
placeholder: "MM / YY",
|
|
899
|
+
style: inputStyle(focusedField === "expiry")
|
|
900
|
+
}
|
|
901
|
+
)
|
|
902
|
+
] }),
|
|
903
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
904
|
+
/* @__PURE__ */ jsx("label", { style: labelStyle, children: "Security code" }),
|
|
905
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
906
|
+
/* @__PURE__ */ jsx(
|
|
907
|
+
"input",
|
|
908
|
+
{
|
|
909
|
+
type: "text",
|
|
910
|
+
value: cvc,
|
|
911
|
+
onChange: (e) => setCvc(e.target.value.replace(/\D/g, "").slice(0, 4)),
|
|
912
|
+
onFocus: () => setFocusedField("cvc"),
|
|
913
|
+
onBlur: () => setFocusedField(null),
|
|
914
|
+
placeholder: "CVC",
|
|
915
|
+
style: inputStyle(focusedField === "cvc")
|
|
916
|
+
}
|
|
917
|
+
),
|
|
918
|
+
/* @__PURE__ */ jsx("div", { style: { position: "absolute", right: "12px", top: "50%", transform: "translateY(-50%)" }, children: /* @__PURE__ */ jsx(CvcIcon, {}) })
|
|
919
|
+
] })
|
|
920
|
+
] })
|
|
921
|
+
] }),
|
|
922
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "14px" }, children: [
|
|
923
|
+
/* @__PURE__ */ jsx("label", { style: labelStyle, children: "Country" }),
|
|
924
|
+
/* @__PURE__ */ jsxs(
|
|
925
|
+
"select",
|
|
926
|
+
{
|
|
927
|
+
value: country,
|
|
928
|
+
onChange: (e) => setCountry(e.target.value),
|
|
929
|
+
onFocus: () => setFocusedField("country"),
|
|
930
|
+
onBlur: () => setFocusedField(null),
|
|
931
|
+
style: {
|
|
932
|
+
...inputStyle(focusedField === "country"),
|
|
933
|
+
appearance: "none",
|
|
934
|
+
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23666' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10z'/%3E%3C/svg%3E")`,
|
|
935
|
+
backgroundRepeat: "no-repeat",
|
|
936
|
+
backgroundPosition: "right 12px center",
|
|
937
|
+
paddingRight: "32px"
|
|
938
|
+
},
|
|
939
|
+
children: [
|
|
940
|
+
/* @__PURE__ */ jsx("option", { children: "Australia" }),
|
|
941
|
+
/* @__PURE__ */ jsx("option", { children: "Austria" }),
|
|
942
|
+
/* @__PURE__ */ jsx("option", { children: "Belgium" }),
|
|
943
|
+
/* @__PURE__ */ jsx("option", { children: "Brazil" }),
|
|
944
|
+
/* @__PURE__ */ jsx("option", { children: "Canada" }),
|
|
945
|
+
/* @__PURE__ */ jsx("option", { children: "Denmark" }),
|
|
946
|
+
/* @__PURE__ */ jsx("option", { children: "Finland" }),
|
|
947
|
+
/* @__PURE__ */ jsx("option", { children: "France" }),
|
|
948
|
+
/* @__PURE__ */ jsx("option", { children: "Germany" }),
|
|
949
|
+
/* @__PURE__ */ jsx("option", { children: "Ireland" }),
|
|
950
|
+
/* @__PURE__ */ jsx("option", { children: "Italy" }),
|
|
951
|
+
/* @__PURE__ */ jsx("option", { children: "Japan" }),
|
|
952
|
+
/* @__PURE__ */ jsx("option", { children: "Netherlands" }),
|
|
953
|
+
/* @__PURE__ */ jsx("option", { children: "New Zealand" }),
|
|
954
|
+
/* @__PURE__ */ jsx("option", { children: "Norway" }),
|
|
955
|
+
/* @__PURE__ */ jsx("option", { children: "Poland" }),
|
|
956
|
+
/* @__PURE__ */ jsx("option", { children: "Portugal" }),
|
|
957
|
+
/* @__PURE__ */ jsx("option", { children: "Spain" }),
|
|
958
|
+
/* @__PURE__ */ jsx("option", { children: "Sweden" }),
|
|
959
|
+
/* @__PURE__ */ jsx("option", { children: "Switzerland" }),
|
|
960
|
+
/* @__PURE__ */ jsx("option", { children: "United Kingdom" }),
|
|
961
|
+
/* @__PURE__ */ jsx("option", { children: "United States" })
|
|
962
|
+
]
|
|
963
|
+
}
|
|
964
|
+
)
|
|
965
|
+
] }),
|
|
966
|
+
/* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: "#6b7280", lineHeight: 1.5, margin: 0, fontFamily: FONT }, children: "By providing your card information, you allow the merchant to charge your card for future payments in accordance with their terms." })
|
|
967
|
+
] });
|
|
968
|
+
}
|
|
969
|
+
function DemoEmbeddedForm({ product, onReady }) {
|
|
970
|
+
const readyFired = useRef(false);
|
|
971
|
+
const [email, setEmail] = useState("");
|
|
972
|
+
const [cardNumber, setCardNumber] = useState("");
|
|
973
|
+
const [expiry, setExpiry] = useState("");
|
|
974
|
+
const [cvc, setCvc] = useState("");
|
|
975
|
+
const [name, setName] = useState("");
|
|
976
|
+
const [country, setCountry] = useState("Denmark");
|
|
977
|
+
const [focusedField, setFocusedField] = useState(null);
|
|
978
|
+
useEffect(() => {
|
|
979
|
+
if (!readyFired.current) {
|
|
980
|
+
readyFired.current = true;
|
|
981
|
+
onReady?.();
|
|
982
|
+
}
|
|
983
|
+
}, [onReady]);
|
|
984
|
+
const formatCardNumber = (val) => {
|
|
985
|
+
const digits = val.replace(/\D/g, "").slice(0, 16);
|
|
986
|
+
return digits.replace(/(.{4})/g, "$1 ").trim();
|
|
987
|
+
};
|
|
988
|
+
const formatExpiry = (val) => {
|
|
989
|
+
const digits = val.replace(/\D/g, "").slice(0, 4);
|
|
990
|
+
if (digits.length > 2) return digits.slice(0, 2) + " / " + digits.slice(2);
|
|
991
|
+
return digits;
|
|
992
|
+
};
|
|
993
|
+
const embeddedInputStyle = (focused) => ({
|
|
994
|
+
width: "100%",
|
|
995
|
+
padding: "10px 12px",
|
|
996
|
+
border: "none",
|
|
997
|
+
borderBottom: `1px solid ${focused ? "#666" : "#e0e0e0"}`,
|
|
998
|
+
fontSize: "14px",
|
|
999
|
+
fontFamily: FONT,
|
|
1000
|
+
outline: "none",
|
|
1001
|
+
backgroundColor: "#fff",
|
|
1002
|
+
boxSizing: "border-box"
|
|
1003
|
+
});
|
|
1004
|
+
const displayPrice = product?.hasTrial ? product.trialPrice : product?.price;
|
|
1005
|
+
return /* @__PURE__ */ jsxs("div", { style: { fontFamily: FONT, border: "1px solid #e0e0e0", borderRadius: "12px", overflow: "hidden", background: "#fff" }, children: [
|
|
1006
|
+
product && /* @__PURE__ */ jsxs("div", { style: { padding: "24px 20px", borderBottom: "1px solid #e0e0e0" }, children: [
|
|
1007
|
+
/* @__PURE__ */ jsxs("div", { style: { fontSize: "14px", color: "#666", marginBottom: "4px" }, children: [
|
|
1008
|
+
"Pay ",
|
|
1009
|
+
product.displayName || product.name
|
|
1010
|
+
] }),
|
|
1011
|
+
/* @__PURE__ */ jsxs("div", { style: { fontSize: "28px", fontWeight: 700, color: "#333", marginBottom: "4px" }, children: [
|
|
1012
|
+
product.currencyCode?.toUpperCase(),
|
|
1013
|
+
displayPrice
|
|
1014
|
+
] }),
|
|
1015
|
+
product.hasTrial && /* @__PURE__ */ jsxs("div", { style: { fontSize: "13px", color: "#666" }, children: [
|
|
1016
|
+
"Then ",
|
|
1017
|
+
/* @__PURE__ */ jsxs("span", { style: { textDecoration: "underline" }, children: [
|
|
1018
|
+
product.currencyCode?.toUpperCase(),
|
|
1019
|
+
product.price
|
|
1020
|
+
] }),
|
|
1021
|
+
" every ",
|
|
1022
|
+
product.period
|
|
1023
|
+
] }),
|
|
1024
|
+
/* @__PURE__ */ jsx(
|
|
1025
|
+
"button",
|
|
1026
|
+
{
|
|
1027
|
+
type: "button",
|
|
1028
|
+
style: {
|
|
1029
|
+
marginTop: "12px",
|
|
1030
|
+
padding: "6px 14px",
|
|
1031
|
+
borderRadius: "6px",
|
|
1032
|
+
border: "1px solid #e0e0e0",
|
|
1033
|
+
backgroundColor: "#fff",
|
|
1034
|
+
color: "#333",
|
|
1035
|
+
fontSize: "13px",
|
|
1036
|
+
cursor: "default",
|
|
1037
|
+
fontFamily: FONT
|
|
1038
|
+
},
|
|
1039
|
+
children: "View details \u25BE"
|
|
1040
|
+
}
|
|
1041
|
+
)
|
|
1042
|
+
] }),
|
|
1043
|
+
/* @__PURE__ */ jsxs("div", { style: { padding: "20px" }, children: [
|
|
1044
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
|
|
1045
|
+
/* @__PURE__ */ jsx("label", { style: { ...labelStyle, fontSize: "13px", color: "#666" }, children: "Email" }),
|
|
1046
|
+
/* @__PURE__ */ jsx(
|
|
1047
|
+
"input",
|
|
1048
|
+
{
|
|
1049
|
+
type: "email",
|
|
1050
|
+
value: email,
|
|
1051
|
+
onChange: (e) => setEmail(e.target.value),
|
|
1052
|
+
onFocus: () => setFocusedField("email"),
|
|
1053
|
+
onBlur: () => setFocusedField(null),
|
|
1054
|
+
placeholder: "you@example.com",
|
|
1055
|
+
style: embeddedInputStyle(focusedField === "email")
|
|
1056
|
+
}
|
|
1057
|
+
)
|
|
1058
|
+
] }),
|
|
1059
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
|
|
1060
|
+
/* @__PURE__ */ jsx("label", { style: { ...labelStyle, fontSize: "13px", color: "#666" }, children: "Card information" }),
|
|
1061
|
+
/* @__PURE__ */ jsxs("div", { style: { border: "1px solid #e0e0e0", borderRadius: "6px", overflow: "hidden" }, children: [
|
|
1062
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
1063
|
+
/* @__PURE__ */ jsx(
|
|
1064
|
+
"input",
|
|
1065
|
+
{
|
|
1066
|
+
type: "text",
|
|
1067
|
+
value: cardNumber,
|
|
1068
|
+
onChange: (e) => setCardNumber(formatCardNumber(e.target.value)),
|
|
1069
|
+
onFocus: () => setFocusedField("card"),
|
|
1070
|
+
onBlur: () => setFocusedField(null),
|
|
1071
|
+
placeholder: "1234 1234 1234 1234",
|
|
1072
|
+
style: { ...embeddedInputStyle(focusedField === "card"), padding: "12px" }
|
|
1073
|
+
}
|
|
1074
|
+
),
|
|
1075
|
+
/* @__PURE__ */ jsx("div", { style: { position: "absolute", right: "12px", top: "50%", transform: "translateY(-50%)" }, children: /* @__PURE__ */ jsx(CardBrandBadges, {}) })
|
|
1076
|
+
] }),
|
|
1077
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr" }, children: [
|
|
1078
|
+
/* @__PURE__ */ jsx(
|
|
1079
|
+
"input",
|
|
1080
|
+
{
|
|
1081
|
+
type: "text",
|
|
1082
|
+
value: expiry,
|
|
1083
|
+
onChange: (e) => setExpiry(formatExpiry(e.target.value)),
|
|
1084
|
+
onFocus: () => setFocusedField("expiry"),
|
|
1085
|
+
onBlur: () => setFocusedField(null),
|
|
1086
|
+
placeholder: "MM / YY",
|
|
1087
|
+
style: { ...embeddedInputStyle(focusedField === "expiry"), borderRight: "1px solid #e0e0e0", padding: "12px" }
|
|
1088
|
+
}
|
|
1089
|
+
),
|
|
1090
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
1091
|
+
/* @__PURE__ */ jsx(
|
|
1092
|
+
"input",
|
|
1093
|
+
{
|
|
1094
|
+
type: "text",
|
|
1095
|
+
value: cvc,
|
|
1096
|
+
onChange: (e) => setCvc(e.target.value.replace(/\D/g, "").slice(0, 4)),
|
|
1097
|
+
onFocus: () => setFocusedField("cvc"),
|
|
1098
|
+
onBlur: () => setFocusedField(null),
|
|
1099
|
+
placeholder: "CVC",
|
|
1100
|
+
style: { ...embeddedInputStyle(focusedField === "cvc"), padding: "12px" }
|
|
1101
|
+
}
|
|
1102
|
+
),
|
|
1103
|
+
/* @__PURE__ */ jsx("div", { style: { position: "absolute", right: "12px", top: "50%", transform: "translateY(-50%)" }, children: /* @__PURE__ */ jsx(CvcIcon, {}) })
|
|
1104
|
+
] })
|
|
1105
|
+
] })
|
|
1106
|
+
] })
|
|
1107
|
+
] }),
|
|
1108
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
|
|
1109
|
+
/* @__PURE__ */ jsx("label", { style: { ...labelStyle, fontSize: "13px", color: "#666" }, children: "Cardholder name" }),
|
|
1110
|
+
/* @__PURE__ */ jsx(
|
|
1111
|
+
"input",
|
|
1112
|
+
{
|
|
1113
|
+
type: "text",
|
|
1114
|
+
value: name,
|
|
1115
|
+
onChange: (e) => setName(e.target.value),
|
|
1116
|
+
onFocus: () => setFocusedField("name"),
|
|
1117
|
+
onBlur: () => setFocusedField(null),
|
|
1118
|
+
placeholder: "Full name on card",
|
|
1119
|
+
style: inputStyle(focusedField === "name")
|
|
1120
|
+
}
|
|
1121
|
+
)
|
|
1122
|
+
] }),
|
|
1123
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "20px" }, children: [
|
|
1124
|
+
/* @__PURE__ */ jsx("label", { style: { ...labelStyle, fontSize: "13px", color: "#666" }, children: "Country or region" }),
|
|
1125
|
+
/* @__PURE__ */ jsxs(
|
|
1126
|
+
"select",
|
|
1127
|
+
{
|
|
1128
|
+
value: country,
|
|
1129
|
+
onChange: (e) => setCountry(e.target.value),
|
|
1130
|
+
onFocus: () => setFocusedField("country"),
|
|
1131
|
+
onBlur: () => setFocusedField(null),
|
|
1132
|
+
style: {
|
|
1133
|
+
...inputStyle(focusedField === "country"),
|
|
1134
|
+
appearance: "none",
|
|
1135
|
+
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23666' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10z'/%3E%3C/svg%3E")`,
|
|
1136
|
+
backgroundRepeat: "no-repeat",
|
|
1137
|
+
backgroundPosition: "right 12px center",
|
|
1138
|
+
paddingRight: "32px"
|
|
1139
|
+
},
|
|
1140
|
+
children: [
|
|
1141
|
+
/* @__PURE__ */ jsx("option", { children: "Australia" }),
|
|
1142
|
+
/* @__PURE__ */ jsx("option", { children: "Austria" }),
|
|
1143
|
+
/* @__PURE__ */ jsx("option", { children: "Belgium" }),
|
|
1144
|
+
/* @__PURE__ */ jsx("option", { children: "Brazil" }),
|
|
1145
|
+
/* @__PURE__ */ jsx("option", { children: "Canada" }),
|
|
1146
|
+
/* @__PURE__ */ jsx("option", { children: "Denmark" }),
|
|
1147
|
+
/* @__PURE__ */ jsx("option", { children: "Finland" }),
|
|
1148
|
+
/* @__PURE__ */ jsx("option", { children: "France" }),
|
|
1149
|
+
/* @__PURE__ */ jsx("option", { children: "Germany" }),
|
|
1150
|
+
/* @__PURE__ */ jsx("option", { children: "Ireland" }),
|
|
1151
|
+
/* @__PURE__ */ jsx("option", { children: "Italy" }),
|
|
1152
|
+
/* @__PURE__ */ jsx("option", { children: "Japan" }),
|
|
1153
|
+
/* @__PURE__ */ jsx("option", { children: "Netherlands" }),
|
|
1154
|
+
/* @__PURE__ */ jsx("option", { children: "New Zealand" }),
|
|
1155
|
+
/* @__PURE__ */ jsx("option", { children: "Norway" }),
|
|
1156
|
+
/* @__PURE__ */ jsx("option", { children: "Poland" }),
|
|
1157
|
+
/* @__PURE__ */ jsx("option", { children: "Portugal" }),
|
|
1158
|
+
/* @__PURE__ */ jsx("option", { children: "Spain" }),
|
|
1159
|
+
/* @__PURE__ */ jsx("option", { children: "Sweden" }),
|
|
1160
|
+
/* @__PURE__ */ jsx("option", { children: "Switzerland" }),
|
|
1161
|
+
/* @__PURE__ */ jsx("option", { children: "United Kingdom" }),
|
|
1162
|
+
/* @__PURE__ */ jsx("option", { children: "United States" })
|
|
1163
|
+
]
|
|
1164
|
+
}
|
|
1165
|
+
)
|
|
1166
|
+
] }),
|
|
1167
|
+
/* @__PURE__ */ jsx(
|
|
1168
|
+
"button",
|
|
1169
|
+
{
|
|
1170
|
+
type: "button",
|
|
1171
|
+
disabled: true,
|
|
1172
|
+
style: {
|
|
1173
|
+
width: "100%",
|
|
1174
|
+
padding: "14px",
|
|
1175
|
+
borderRadius: "6px",
|
|
1176
|
+
border: "none",
|
|
1177
|
+
backgroundColor: "#0570de",
|
|
1178
|
+
color: "#fff",
|
|
1179
|
+
fontSize: "16px",
|
|
1180
|
+
fontWeight: 600,
|
|
1181
|
+
cursor: "default",
|
|
1182
|
+
fontFamily: FONT,
|
|
1183
|
+
opacity: 0.7
|
|
1184
|
+
},
|
|
1185
|
+
children: "Subscribe"
|
|
1186
|
+
}
|
|
1187
|
+
),
|
|
1188
|
+
/* @__PURE__ */ jsxs("div", { style: { textAlign: "center", marginTop: "12px", fontSize: "12px", color: "#aaa" }, children: [
|
|
1189
|
+
"Powered by ",
|
|
1190
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 700, letterSpacing: "-0.3px" }, children: "stripe" })
|
|
1191
|
+
] })
|
|
1192
|
+
] })
|
|
1193
|
+
] });
|
|
1194
|
+
}
|
|
1195
|
+
var DemoStripePaymentForm = forwardRef(
|
|
1196
|
+
function DemoStripePaymentForm2({
|
|
1197
|
+
productId,
|
|
1198
|
+
mode = "checkout",
|
|
1199
|
+
variant = "elements",
|
|
1200
|
+
onSuccess,
|
|
1201
|
+
onError,
|
|
1202
|
+
onReady,
|
|
1203
|
+
className
|
|
1204
|
+
}, ref) {
|
|
1205
|
+
const { variableStore, tracker, products } = useFunnelContext();
|
|
1206
|
+
const validateOnly = mode === "validate-only";
|
|
1207
|
+
const product = useMemo(() => {
|
|
1208
|
+
if (productId) return products.find((p) => p.id === productId) || null;
|
|
1209
|
+
const selectedId = variableStore.get("products.selectedProductId");
|
|
1210
|
+
return products.find((p) => p.id === selectedId) || null;
|
|
1211
|
+
}, [productId, products, variableStore]);
|
|
1212
|
+
const hasFiredStart = useRef(false);
|
|
1213
|
+
useEffect(() => {
|
|
1214
|
+
if (hasFiredStart.current) return;
|
|
1215
|
+
hasFiredStart.current = true;
|
|
1216
|
+
variableStore.set("payment.loading", false);
|
|
1217
|
+
tracker.track("checkout.start", {
|
|
1218
|
+
productId: product?.id,
|
|
1219
|
+
priceId: product?.stripePriceId || product?.storePriceId,
|
|
1220
|
+
productName: product?.displayName
|
|
1221
|
+
});
|
|
1222
|
+
}, [product, tracker, variableStore]);
|
|
1223
|
+
const handleSubmit = useCallback(async () => {
|
|
1224
|
+
variableStore.set("payment.loading", true);
|
|
1225
|
+
await new Promise((r) => setTimeout(r, 800));
|
|
1226
|
+
try {
|
|
1227
|
+
tracker.track("checkout.payment_added");
|
|
1228
|
+
if (validateOnly) {
|
|
1229
|
+
variableStore.setMany({
|
|
1230
|
+
"card.last4": "4242",
|
|
1231
|
+
"card.brand": "visa",
|
|
1232
|
+
"card.expMonth": 12,
|
|
1233
|
+
"card.expYear": 2030,
|
|
1234
|
+
"card.funding": "credit",
|
|
1235
|
+
"payment.error": ""
|
|
1236
|
+
});
|
|
1237
|
+
onSuccess?.();
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
variableStore.set("payment.error", "");
|
|
1241
|
+
tracker.track("purchase.complete", {
|
|
1242
|
+
amount: product?.rawPrice ? product.rawPrice / 100 : 0,
|
|
1243
|
+
currency: product?.currencyCode || "USD"
|
|
1244
|
+
});
|
|
1245
|
+
onSuccess?.();
|
|
1246
|
+
} catch (err) {
|
|
1247
|
+
const msg = err instanceof Error ? err.message : "An error occurred";
|
|
1248
|
+
variableStore.set("payment.error", msg);
|
|
1249
|
+
onError?.(msg);
|
|
1250
|
+
} finally {
|
|
1251
|
+
variableStore.set("payment.loading", false);
|
|
1252
|
+
}
|
|
1253
|
+
}, [validateOnly, variableStore, tracker, product, onSuccess, onError]);
|
|
1254
|
+
useImperativeHandle(ref, () => ({ submit: handleSubmit }), [handleSubmit]);
|
|
1255
|
+
return /* @__PURE__ */ jsx("div", { className, children: variant === "embedded" ? /* @__PURE__ */ jsx(DemoEmbeddedForm, { product, onReady }) : /* @__PURE__ */ jsx(DemoElementsForm, { onReady }) });
|
|
1256
|
+
}
|
|
1257
|
+
);
|
|
1258
|
+
var API_BASE_URL2 = "https://api.appfunnel.net";
|
|
1259
|
+
var isDevMode = () => typeof globalThis !== "undefined" && !!globalThis.__APPFUNNEL_DEV__;
|
|
579
1260
|
var InnerPaymentForm = forwardRef(
|
|
580
1261
|
function InnerPaymentForm2({ paymentMode, validateOnly, onSuccess, onError, onReady, layout }, ref) {
|
|
581
1262
|
const stripe = useStripe();
|
|
@@ -623,7 +1304,7 @@ var InnerPaymentForm = forwardRef(
|
|
|
623
1304
|
return;
|
|
624
1305
|
}
|
|
625
1306
|
const response2 = await fetch(
|
|
626
|
-
`${
|
|
1307
|
+
`${API_BASE_URL2}/campaign/${campaignId}/stripe/validate-card`,
|
|
627
1308
|
{
|
|
628
1309
|
method: "POST",
|
|
629
1310
|
headers: { "Content-Type": "application/json" },
|
|
@@ -664,7 +1345,7 @@ var InnerPaymentForm = forwardRef(
|
|
|
664
1345
|
return;
|
|
665
1346
|
}
|
|
666
1347
|
const response = await fetch(
|
|
667
|
-
`${
|
|
1348
|
+
`${API_BASE_URL2}/campaign/${campaignId}/stripe/purchase`,
|
|
668
1349
|
{
|
|
669
1350
|
method: "POST",
|
|
670
1351
|
headers: { "Content-Type": "application/json" },
|
|
@@ -709,11 +1390,15 @@ var InnerPaymentForm = forwardRef(
|
|
|
709
1390
|
] });
|
|
710
1391
|
}
|
|
711
1392
|
);
|
|
712
|
-
var
|
|
713
|
-
function
|
|
1393
|
+
var RealStripePaymentForm = forwardRef(
|
|
1394
|
+
function RealStripePaymentForm2({
|
|
714
1395
|
productId,
|
|
715
1396
|
mode = "checkout",
|
|
716
1397
|
variant = "elements",
|
|
1398
|
+
successPageKey,
|
|
1399
|
+
automaticTax = false,
|
|
1400
|
+
managedPayments = false,
|
|
1401
|
+
allowPromotionCodes = false,
|
|
717
1402
|
onSuccess,
|
|
718
1403
|
onError,
|
|
719
1404
|
onReady,
|
|
@@ -721,7 +1406,7 @@ var StripePaymentForm = forwardRef(
|
|
|
721
1406
|
appearance,
|
|
722
1407
|
layout
|
|
723
1408
|
}, ref) {
|
|
724
|
-
const { campaignId, tracker, variableStore, products } = useFunnelContext();
|
|
1409
|
+
const { campaignId, tracker, variableStore, products, router } = useFunnelContext();
|
|
725
1410
|
const [email] = useVariable("user.email");
|
|
726
1411
|
const validateOnly = mode === "validate-only";
|
|
727
1412
|
const product = useMemo(() => {
|
|
@@ -748,18 +1433,36 @@ var StripePaymentForm = forwardRef(
|
|
|
748
1433
|
const createIntent = async () => {
|
|
749
1434
|
try {
|
|
750
1435
|
if (variant === "embedded") {
|
|
1436
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
1437
|
+
let returnUrl = origin + "/";
|
|
1438
|
+
if (successPageKey) {
|
|
1439
|
+
const pageUrl = router.getPageUrl(successPageKey);
|
|
1440
|
+
returnUrl = `${origin}${pageUrl}?checkout=success&session_id={CHECKOUT_SESSION_ID}`;
|
|
1441
|
+
}
|
|
1442
|
+
const apiCheckoutMode = managedPayments ? "embedded" : variant;
|
|
1443
|
+
const body = {
|
|
1444
|
+
campaignId,
|
|
1445
|
+
sessionId: tracker.getSessionId(),
|
|
1446
|
+
customerEmail: email,
|
|
1447
|
+
priceId: product.storePriceId,
|
|
1448
|
+
returnUrl,
|
|
1449
|
+
checkoutMode: apiCheckoutMode,
|
|
1450
|
+
automaticTax,
|
|
1451
|
+
managedPayments,
|
|
1452
|
+
allowPromotionCodes
|
|
1453
|
+
};
|
|
1454
|
+
if (product.hasTrial && product.trialDays > 0) {
|
|
1455
|
+
body.trialPeriodDays = product.trialDays;
|
|
1456
|
+
if (product.paidTrial && product.trialStorePriceId) {
|
|
1457
|
+
body.paidTrialPriceId = product.trialStorePriceId;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
751
1460
|
const response = await fetch(
|
|
752
|
-
`${
|
|
1461
|
+
`${API_BASE_URL2}/campaign/${campaignId}/stripe/checkout-session`,
|
|
753
1462
|
{
|
|
754
1463
|
method: "POST",
|
|
755
1464
|
headers: { "Content-Type": "application/json" },
|
|
756
|
-
body: JSON.stringify(
|
|
757
|
-
campaignId,
|
|
758
|
-
sessionId: tracker.getSessionId(),
|
|
759
|
-
customerEmail: email,
|
|
760
|
-
priceId: product.storePriceId,
|
|
761
|
-
trialPeriodDays: product.hasTrial ? product.trialDays : void 0
|
|
762
|
-
})
|
|
1465
|
+
body: JSON.stringify(body)
|
|
763
1466
|
}
|
|
764
1467
|
);
|
|
765
1468
|
const result = await response.json();
|
|
@@ -775,7 +1478,7 @@ var StripePaymentForm = forwardRef(
|
|
|
775
1478
|
priceId: product.storePriceId
|
|
776
1479
|
};
|
|
777
1480
|
if (validateOnly) body.validateOnly = true;
|
|
778
|
-
const response = await fetch(`${
|
|
1481
|
+
const response = await fetch(`${API_BASE_URL2}${endpoint}`, {
|
|
779
1482
|
method: "POST",
|
|
780
1483
|
headers: { "Content-Type": "application/json" },
|
|
781
1484
|
body: JSON.stringify(body)
|
|
@@ -801,7 +1504,7 @@ var StripePaymentForm = forwardRef(
|
|
|
801
1504
|
}
|
|
802
1505
|
};
|
|
803
1506
|
createIntent();
|
|
804
|
-
}, [email, campaignId, product, paymentMode, validateOnly, variant, tracker, variableStore]);
|
|
1507
|
+
}, [email, campaignId, product, paymentMode, validateOnly, variant, successPageKey, automaticTax, managedPayments, allowPromotionCodes, router, tracker, variableStore]);
|
|
805
1508
|
if (isLoading) {
|
|
806
1509
|
return /* @__PURE__ */ jsx("div", { className, style: { padding: "20px", textAlign: "center", color: "#6b7280" }, children: "Loading payment form..." });
|
|
807
1510
|
}
|
|
@@ -819,16 +1522,7 @@ var StripePaymentForm = forwardRef(
|
|
|
819
1522
|
EmbeddedCheckoutProvider,
|
|
820
1523
|
{
|
|
821
1524
|
stripe: stripePromise,
|
|
822
|
-
options: {
|
|
823
|
-
clientSecret,
|
|
824
|
-
onComplete: () => {
|
|
825
|
-
tracker.track("purchase.complete", {
|
|
826
|
-
amount: product?.rawPrice ? product.rawPrice / 100 : 0,
|
|
827
|
-
currency: product?.currencyCode || "USD"
|
|
828
|
-
});
|
|
829
|
-
onSuccess?.();
|
|
830
|
-
}
|
|
831
|
-
},
|
|
1525
|
+
options: { clientSecret },
|
|
832
1526
|
children: /* @__PURE__ */ jsx(EmbeddedCheckout, {})
|
|
833
1527
|
}
|
|
834
1528
|
) });
|
|
@@ -851,6 +1545,14 @@ var StripePaymentForm = forwardRef(
|
|
|
851
1545
|
) }) });
|
|
852
1546
|
}
|
|
853
1547
|
);
|
|
1548
|
+
var StripePaymentForm = forwardRef(
|
|
1549
|
+
function StripePaymentForm2(props, ref) {
|
|
1550
|
+
if (isDevMode()) {
|
|
1551
|
+
return /* @__PURE__ */ jsx(DemoStripePaymentForm, { ref, ...props });
|
|
1552
|
+
}
|
|
1553
|
+
return /* @__PURE__ */ jsx(RealStripePaymentForm, { ref, ...props });
|
|
1554
|
+
}
|
|
1555
|
+
);
|
|
854
1556
|
function PaddleCheckout({
|
|
855
1557
|
productId,
|
|
856
1558
|
mode = "overlay",
|