stripe 1/2

This commit is contained in:
lovebird 2026-02-21 09:40:48 +01:00
parent 4e07182722
commit 5fbffdee5e
6 changed files with 368 additions and 302 deletions

View File

@ -39,8 +39,16 @@ export interface CheckoutPageProps {
stripePromise?: Promise<StripeJS | null> | null;
/** Stripe PaymentIntent client secret. */
stripeClientSecret?: string | null;
/** Called after Stripe payment succeeds inline (no redirect). */
onStripePaymentSuccess?: () => void;
/** Called after Stripe payment succeeds — includes shipping data and PaymentIntent. */
onStripePaymentSuccess?: (data: {
shipping: ShippingAddress;
paymentMethod: PaymentMethod;
paymentIntent: {
id: string;
status: string;
[key: string]: any;
};
}) => void;
/** Stripe return URL for redirect-based payment methods. */
stripeReturnUrl?: string;
/** Optional extra class names. */

View File

@ -1,6 +1,10 @@
export interface StripePaymentFormProps {
/** Called after Stripe confirms payment successfully. */
onPaymentSuccess?: () => void;
/** Called after Stripe confirms payment — receives the PaymentIntent data. */
onPaymentSuccess?: (paymentIntent: {
id: string;
status: string;
[key: string]: any;
}) => void;
/** Return URL after redirect-based payment methods (iDEAL, etc.). */
returnUrl?: string;
/** Pre-fill the email field. */

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -144,9 +144,28 @@ export function CheckoutFlow({
};
// 6. Handle Stripe payment success (inline, no redirect)
const handleStripePaymentSuccess = () => {
toast?.success("Payment successful!");
onOrderSuccess();
const handleStripePaymentSuccess = async (data: {
shipping: any;
paymentMethod: string;
paymentIntent: { id: string; status: string;[key: string]: any };
}) => {
try {
await onPlaceOrder({
shipping: data.shipping,
paymentMethod: data.paymentMethod,
// Store Stripe PaymentIntent ID for refunds/reconciliation
external_order_id: data.paymentIntent.id,
metadata: {
stripe_payment_intent_id: data.paymentIntent.id,
stripe_status: data.paymentIntent.status,
},
});
toast?.success("Payment successful!");
onOrderSuccess();
} catch (err) {
console.error("Failed to record Stripe transaction:", err);
toast?.error("Payment succeeded but failed to record transaction. Contact support.");
}
};
return (

View File

@ -56,8 +56,12 @@ export interface CheckoutPageProps {
stripePromise?: Promise<StripeJS | null> | null;
/** Stripe PaymentIntent client secret. */
stripeClientSecret?: string | null;
/** Called after Stripe payment succeeds inline (no redirect). */
onStripePaymentSuccess?: () => void;
/** Called after Stripe payment succeeds — includes shipping data and PaymentIntent. */
onStripePaymentSuccess?: (data: {
shipping: ShippingAddress;
paymentMethod: PaymentMethod;
paymentIntent: { id: string; status: string;[key: string]: any };
}) => void;
/** Stripe return URL for redirect-based payment methods. */
stripeReturnUrl?: string;
/** Optional extra class names. */
@ -369,7 +373,16 @@ export function CheckoutPage({
<div className="pt-2" style={{ minHeight: 350, contain: "content", overflow: "hidden", maxWidth: "100%" }}>
<Elements stripe={stripePromise} options={{ clientSecret: stripeClientSecret }}>
<StripePaymentForm
onPaymentSuccess={onStripePaymentSuccess}
onPaymentSuccess={(paymentIntent) => {
if (saveAddress && selectedAddressId === "custom" && onSaveAddress) {
onSaveAddress(form);
}
onStripePaymentSuccess?.({
shipping: form,
paymentMethod: "stripe",
paymentIntent,
});
}}
returnUrl={stripeReturnUrl}
defaultEmail={form.email}
defaultName={form.fullName}