98 lines
No EOL
2.6 KiB
JavaScript
98 lines
No EOL
2.6 KiB
JavaScript
import React, { useState } from 'react';
|
|
import {
|
|
PaymentElement,
|
|
useStripe as useStripeJs,
|
|
useElements
|
|
} from '@stripe/react-stripe-js';
|
|
import { Box, Button, CircularProgress, Alert, Typography } from '@mui/material';
|
|
import { useStripe } from '../context/StripeContext';
|
|
|
|
const StripePaymentForm = ({ orderId, onSuccess, onError }) => {
|
|
const stripe = useStripeJs();
|
|
const elements = useElements();
|
|
const { completeOrder } = useStripe();
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [message, setMessage] = useState(null);
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault();
|
|
|
|
if (!stripe || !elements) {
|
|
// Stripe.js hasn't loaded yet
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
setMessage(null);
|
|
|
|
try {
|
|
// Submit the form
|
|
const { error, paymentIntent } = await stripe.confirmPayment({
|
|
elements,
|
|
confirmParams: {
|
|
return_url: `${window.location.origin}/checkout/confirmation?order_id=${orderId}`,
|
|
},
|
|
redirect: 'if_required',
|
|
});
|
|
|
|
if (error) {
|
|
setMessage(error.message || 'An unexpected error occurred');
|
|
onError(error.message);
|
|
} else if (paymentIntent && paymentIntent.status === 'succeeded') {
|
|
// Call our backend to update the order status
|
|
await completeOrder(orderId, paymentIntent.id);
|
|
setMessage('Payment successful!');
|
|
onSuccess(paymentIntent);
|
|
} else {
|
|
setMessage('Payment processing. Please wait for confirmation.');
|
|
}
|
|
} catch (err) {
|
|
console.error('Payment error:', err);
|
|
setMessage(err.message || 'An error occurred during payment processing');
|
|
onError(err.message);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Box component="form" onSubmit={handleSubmit} sx={{ width: '100%' }}>
|
|
{message && (
|
|
<Alert
|
|
severity={message.includes('successful') ? 'success' : 'error'}
|
|
sx={{ mb: 3 }}
|
|
>
|
|
{message}
|
|
</Alert>
|
|
)}
|
|
|
|
<Typography variant="h6" gutterBottom>
|
|
Enter your payment details
|
|
</Typography>
|
|
|
|
<Box sx={{ mb: 3 }}>
|
|
<PaymentElement />
|
|
</Box>
|
|
|
|
<Button
|
|
type="submit"
|
|
variant="contained"
|
|
color="primary"
|
|
fullWidth
|
|
size="large"
|
|
disabled={isLoading || !stripe || !elements}
|
|
>
|
|
{isLoading ? (
|
|
<>
|
|
<CircularProgress size={24} sx={{ mr: 1 }} />
|
|
Processing...
|
|
</>
|
|
) : (
|
|
'Pay Now'
|
|
)}
|
|
</Button>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default StripePaymentForm; |