Add Mollie payment integration to CartTab and OrderProcessingService
- Introduced Mollie payment method in CartTab, allowing users to select it alongside existing payment options. - Implemented loading and error handling for the Mollie component. - Updated OrderProcessingService to create Mollie payment intents. - Adjusted PaymentMethodSelector to switch to Mollie when specific delivery methods are selected. - Enhanced CartTab to store cart items for Mollie payments and calculate total amounts accordingly.
This commit is contained in:
381
src/components/Mollie.js
Normal file
381
src/components/Mollie.js
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
import React, { Component, useState } from "react";
|
||||||
|
import { Button, Box, Typography, CircularProgress } from "@mui/material";
|
||||||
|
import config from "../config.js";
|
||||||
|
|
||||||
|
// Function to lazy load Mollie script
|
||||||
|
const loadMollie = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Check if Mollie is already loaded
|
||||||
|
if (window.Mollie) {
|
||||||
|
resolve(window.Mollie);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create script element
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = 'https://js.mollie.com/v1/mollie.js';
|
||||||
|
script.async = true;
|
||||||
|
|
||||||
|
script.onload = () => {
|
||||||
|
if (window.Mollie) {
|
||||||
|
resolve(window.Mollie);
|
||||||
|
} else {
|
||||||
|
reject(new Error('Mollie failed to load'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
script.onerror = () => {
|
||||||
|
reject(new Error('Failed to load Mollie script'));
|
||||||
|
};
|
||||||
|
|
||||||
|
document.head.appendChild(script);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const CheckoutForm = ({ mollie }) => {
|
||||||
|
const [errorMessage, setErrorMessage] = useState(null);
|
||||||
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!mollie) return;
|
||||||
|
|
||||||
|
let mountedComponents = {
|
||||||
|
cardNumber: null,
|
||||||
|
cardHolder: null,
|
||||||
|
expiryDate: null,
|
||||||
|
verificationCode: null
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create Mollie components
|
||||||
|
const cardNumber = mollie.createComponent('cardNumber');
|
||||||
|
const cardHolder = mollie.createComponent('cardHolder');
|
||||||
|
const expiryDate = mollie.createComponent('expiryDate');
|
||||||
|
const verificationCode = mollie.createComponent('verificationCode');
|
||||||
|
|
||||||
|
// Store references for cleanup
|
||||||
|
mountedComponents = {
|
||||||
|
cardNumber,
|
||||||
|
cardHolder,
|
||||||
|
expiryDate,
|
||||||
|
verificationCode
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mount components
|
||||||
|
cardNumber.mount('#card-number');
|
||||||
|
cardHolder.mount('#card-holder');
|
||||||
|
expiryDate.mount('#expiry-date');
|
||||||
|
verificationCode.mount('#verification-code');
|
||||||
|
|
||||||
|
// Set up error handling
|
||||||
|
cardNumber.addEventListener('change', event => {
|
||||||
|
const errorElement = document.querySelector('#card-number-error');
|
||||||
|
if (errorElement) {
|
||||||
|
if (event.error && event.touched) {
|
||||||
|
errorElement.textContent = event.error;
|
||||||
|
} else {
|
||||||
|
errorElement.textContent = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cardHolder.addEventListener('change', event => {
|
||||||
|
const errorElement = document.querySelector('#card-holder-error');
|
||||||
|
if (errorElement) {
|
||||||
|
if (event.error && event.touched) {
|
||||||
|
errorElement.textContent = event.error;
|
||||||
|
} else {
|
||||||
|
errorElement.textContent = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expiryDate.addEventListener('change', event => {
|
||||||
|
const errorElement = document.querySelector('#expiry-date-error');
|
||||||
|
if (errorElement) {
|
||||||
|
if (event.error && event.touched) {
|
||||||
|
errorElement.textContent = event.error;
|
||||||
|
} else {
|
||||||
|
errorElement.textContent = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
verificationCode.addEventListener('change', event => {
|
||||||
|
const errorElement = document.querySelector('#verification-code-error');
|
||||||
|
if (errorElement) {
|
||||||
|
if (event.error && event.touched) {
|
||||||
|
errorElement.textContent = event.error;
|
||||||
|
} else {
|
||||||
|
errorElement.textContent = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Components are now mounted and ready
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating Mollie components:', error);
|
||||||
|
setErrorMessage('Failed to initialize payment form. Please try again.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup function
|
||||||
|
return () => {
|
||||||
|
try {
|
||||||
|
if (mountedComponents.cardNumber) mountedComponents.cardNumber.unmount();
|
||||||
|
if (mountedComponents.cardHolder) mountedComponents.cardHolder.unmount();
|
||||||
|
if (mountedComponents.expiryDate) mountedComponents.expiryDate.unmount();
|
||||||
|
if (mountedComponents.verificationCode) mountedComponents.verificationCode.unmount();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error cleaning up Mollie components:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [mollie]);
|
||||||
|
|
||||||
|
const handleSubmit = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (!mollie || isSubmitting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsSubmitting(true);
|
||||||
|
setErrorMessage(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { token, error } = await mollie.createToken();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
setErrorMessage(error.message || 'Payment failed. Please try again.');
|
||||||
|
setIsSubmitting(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
// Handle successful token creation
|
||||||
|
// Create a payment completion event similar to Stripe
|
||||||
|
const mollieCompletionData = {
|
||||||
|
mollieToken: token,
|
||||||
|
paymentMethod: 'mollie'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Dispatch a custom event to notify the parent component
|
||||||
|
const completionEvent = new CustomEvent('molliePaymentComplete', {
|
||||||
|
detail: mollieCompletionData
|
||||||
|
});
|
||||||
|
window.dispatchEvent(completionEvent);
|
||||||
|
|
||||||
|
// For now, redirect to profile with completion data
|
||||||
|
const returnUrl = `${window.location.origin}/profile?complete&mollie_token=${token}`;
|
||||||
|
window.location.href = returnUrl;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating Mollie token:', error);
|
||||||
|
setErrorMessage('Payment failed. Please try again.');
|
||||||
|
setIsSubmitting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ maxWidth: 600, mx: 'auto', p: 3 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
Kreditkarte oder Sofortüberweisung
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Box sx={{ mb: 3 }}>
|
||||||
|
<Typography variant="body2" gutterBottom>
|
||||||
|
Kartennummer
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
id="card-number"
|
||||||
|
sx={{
|
||||||
|
p: 2,
|
||||||
|
border: '1px solid #e0e0e0',
|
||||||
|
borderRadius: 1,
|
||||||
|
minHeight: 40,
|
||||||
|
backgroundColor: '#fff'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
id="card-number-error"
|
||||||
|
variant="caption"
|
||||||
|
sx={{ color: 'error.main', minHeight: 16, display: 'block' }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ mb: 3 }}>
|
||||||
|
<Typography variant="body2" gutterBottom>
|
||||||
|
Karteninhaber
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
id="card-holder"
|
||||||
|
sx={{
|
||||||
|
p: 2,
|
||||||
|
border: '1px solid #e0e0e0',
|
||||||
|
borderRadius: 1,
|
||||||
|
minHeight: 40,
|
||||||
|
backgroundColor: '#fff'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
id="card-holder-error"
|
||||||
|
variant="caption"
|
||||||
|
sx={{ color: 'error.main', minHeight: 16, display: 'block' }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', gap: 2, mb: 3 }}>
|
||||||
|
<Box sx={{ flex: 1 }}>
|
||||||
|
<Typography variant="body2" gutterBottom>
|
||||||
|
Ablaufdatum
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
id="expiry-date"
|
||||||
|
sx={{
|
||||||
|
p: 2,
|
||||||
|
border: '1px solid #e0e0e0',
|
||||||
|
borderRadius: 1,
|
||||||
|
minHeight: 40,
|
||||||
|
backgroundColor: '#fff'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
id="expiry-date-error"
|
||||||
|
variant="caption"
|
||||||
|
sx={{ color: 'error.main', minHeight: 16, display: 'block' }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ flex: 1 }}>
|
||||||
|
<Typography variant="body2" gutterBottom>
|
||||||
|
Sicherheitscode
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
id="verification-code"
|
||||||
|
sx={{
|
||||||
|
p: 2,
|
||||||
|
border: '1px solid #e0e0e0',
|
||||||
|
borderRadius: 1,
|
||||||
|
minHeight: 40,
|
||||||
|
backgroundColor: '#fff'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
id="verification-code-error"
|
||||||
|
variant="caption"
|
||||||
|
sx={{ color: 'error.main', minHeight: 16, display: 'block' }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
disabled={!mollie || isSubmitting}
|
||||||
|
type="submit"
|
||||||
|
fullWidth
|
||||||
|
sx={{
|
||||||
|
mt: 2,
|
||||||
|
backgroundColor: '#2e7d32',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: '#1b5e20'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isSubmitting ? (
|
||||||
|
<>
|
||||||
|
<CircularProgress size={20} sx={{ mr: 1, color: 'white' }} />
|
||||||
|
Verarbeitung...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
'Bezahlung Abschließen'
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{errorMessage && (
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
sx={{ color: 'error.main', mt: 2, textAlign: 'center' }}
|
||||||
|
>
|
||||||
|
{errorMessage}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Mollie extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
mollie: null,
|
||||||
|
loading: true,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
this.molliePromise = loadMollie();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.molliePromise
|
||||||
|
.then((MollieClass) => {
|
||||||
|
try {
|
||||||
|
// Initialize Mollie with profile key
|
||||||
|
const mollie = MollieClass(config.mollieProfileKey, {
|
||||||
|
locale: 'de_DE',
|
||||||
|
testmode: true // Set to false for production
|
||||||
|
});
|
||||||
|
this.setState({ mollie, loading: false });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error initializing Mollie:', error);
|
||||||
|
this.setState({
|
||||||
|
error: 'Failed to initialize payment system. Please try again.',
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error loading Mollie:', error);
|
||||||
|
this.setState({
|
||||||
|
error: 'Failed to load payment system. Please try again.',
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { mollie, loading, error } = this.state;
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<Box sx={{ textAlign: 'center', py: 4 }}>
|
||||||
|
<CircularProgress sx={{ color: '#2e7d32' }} />
|
||||||
|
<Typography variant="body1" sx={{ mt: 2 }}>
|
||||||
|
Zahlungskomponente wird geladen...
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<Box sx={{ textAlign: 'center', py: 4 }}>
|
||||||
|
<Typography variant="body1" sx={{ color: 'error.main' }}>
|
||||||
|
{error}
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
sx={{ mt: 2 }}
|
||||||
|
>
|
||||||
|
Seite neu laden
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <CheckoutForm mollie={mollie} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Mollie;
|
||||||
@@ -51,6 +51,9 @@ class CartTab extends Component {
|
|||||||
showStripePayment: false,
|
showStripePayment: false,
|
||||||
StripeComponent: null,
|
StripeComponent: null,
|
||||||
isLoadingStripe: false,
|
isLoadingStripe: false,
|
||||||
|
showMolliePayment: false,
|
||||||
|
MollieComponent: null,
|
||||||
|
isLoadingMollie: false,
|
||||||
showPaymentConfirmation: false,
|
showPaymentConfirmation: false,
|
||||||
orderCompleted: false,
|
orderCompleted: false,
|
||||||
originalCartItems: []
|
originalCartItems: []
|
||||||
@@ -116,7 +119,7 @@ class CartTab extends Component {
|
|||||||
// Determine payment method - respect constraints
|
// Determine payment method - respect constraints
|
||||||
let prefillPaymentMethod = template.payment_method || "wire";
|
let prefillPaymentMethod = template.payment_method || "wire";
|
||||||
const paymentMethodMap = {
|
const paymentMethodMap = {
|
||||||
"credit_card": "stripe",
|
"credit_card": "mollie",//stripe
|
||||||
"bank_transfer": "wire",
|
"bank_transfer": "wire",
|
||||||
"cash_on_delivery": "onDelivery",
|
"cash_on_delivery": "onDelivery",
|
||||||
"cash": "cash"
|
"cash": "cash"
|
||||||
@@ -319,6 +322,27 @@ class CartTab extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
loadMollieComponent = async () => {
|
||||||
|
this.setState({ isLoadingMollie: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { default: Mollie } = await import("../Mollie.js");
|
||||||
|
this.setState({
|
||||||
|
MollieComponent: Mollie,
|
||||||
|
showMolliePayment: true,
|
||||||
|
isCompletingOrder: false,
|
||||||
|
isLoadingMollie: false,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to load Mollie component:", error);
|
||||||
|
this.setState({
|
||||||
|
isCompletingOrder: false,
|
||||||
|
isLoadingMollie: false,
|
||||||
|
completionError: "Failed to load payment component. Please try again.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
handleCompleteOrder = () => {
|
handleCompleteOrder = () => {
|
||||||
this.setState({ completionError: null }); // Clear previous errors
|
this.setState({ completionError: null }); // Clear previous errors
|
||||||
|
|
||||||
@@ -363,6 +387,25 @@ class CartTab extends Component {
|
|||||||
this.orderService.createStripeIntent(totalAmount, this.loadStripeComponent);
|
this.orderService.createStripeIntent(totalAmount, this.loadStripeComponent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Handle Mollie payment differently
|
||||||
|
if (paymentMethod === "mollie") {
|
||||||
|
// Store the cart items used for Mollie payment in sessionStorage for later reference
|
||||||
|
try {
|
||||||
|
sessionStorage.setItem('molliePaymentCart', JSON.stringify(cartItems));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to store Mollie payment cart:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate total amount for Mollie
|
||||||
|
const subtotal = cartItems.reduce(
|
||||||
|
(total, item) => total + item.price * item.quantity,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
const totalAmount = Math.round((subtotal + deliveryCost) * 100); // Convert to cents
|
||||||
|
|
||||||
|
this.orderService.createMollieIntent(totalAmount, this.loadMollieComponent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle regular orders
|
// Handle regular orders
|
||||||
const orderData = {
|
const orderData = {
|
||||||
@@ -398,6 +441,9 @@ class CartTab extends Component {
|
|||||||
showStripePayment,
|
showStripePayment,
|
||||||
StripeComponent,
|
StripeComponent,
|
||||||
isLoadingStripe,
|
isLoadingStripe,
|
||||||
|
showMolliePayment,
|
||||||
|
MollieComponent,
|
||||||
|
isLoadingMollie,
|
||||||
showPaymentConfirmation,
|
showPaymentConfirmation,
|
||||||
orderCompleted,
|
orderCompleted,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
@@ -434,7 +480,7 @@ class CartTab extends Component {
|
|||||||
<CartDropdown
|
<CartDropdown
|
||||||
cartItems={cartItems}
|
cartItems={cartItems}
|
||||||
socket={this.context.socket}
|
socket={this.context.socket}
|
||||||
showDetailedSummary={showStripePayment}
|
showDetailedSummary={showStripePayment || showMolliePayment}
|
||||||
deliveryMethod={deliveryMethod}
|
deliveryMethod={deliveryMethod}
|
||||||
deliveryCost={deliveryCost}
|
deliveryCost={deliveryCost}
|
||||||
/>
|
/>
|
||||||
@@ -442,7 +488,7 @@ class CartTab extends Component {
|
|||||||
|
|
||||||
{cartItems.length > 0 && (
|
{cartItems.length > 0 && (
|
||||||
<Box sx={{ mt: 3 }}>
|
<Box sx={{ mt: 3 }}>
|
||||||
{isLoadingStripe ? (
|
{isLoadingStripe || isLoadingMollie ? (
|
||||||
<Box sx={{ textAlign: 'center', py: 4 }}>
|
<Box sx={{ textAlign: 'center', py: 4 }}>
|
||||||
<Typography variant="body1">
|
<Typography variant="body1">
|
||||||
Zahlungskomponente wird geladen...
|
Zahlungskomponente wird geladen...
|
||||||
@@ -468,6 +514,26 @@ class CartTab extends Component {
|
|||||||
</Box>
|
</Box>
|
||||||
<StripeComponent clientSecret={stripeClientSecret} />
|
<StripeComponent clientSecret={stripeClientSecret} />
|
||||||
</>
|
</>
|
||||||
|
) : showMolliePayment && MollieComponent ? (
|
||||||
|
<>
|
||||||
|
<Box sx={{ mb: 2 }}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => this.setState({ showMolliePayment: false })}
|
||||||
|
sx={{
|
||||||
|
color: '#2e7d32',
|
||||||
|
borderColor: '#2e7d32',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(46, 125, 50, 0.04)',
|
||||||
|
borderColor: '#1b5e20'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
← Zurück zur Bestellung
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<MollieComponent />
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<CheckoutForm
|
<CheckoutForm
|
||||||
paymentMethod={paymentMethod}
|
paymentMethod={paymentMethod}
|
||||||
|
|||||||
@@ -270,6 +270,10 @@ class OrderProcessingService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Create Mollie payment intent
|
||||||
|
createMollieIntent(totalAmount, loadMollieComponent) {
|
||||||
|
loadMollieComponent();
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate delivery cost
|
// Calculate delivery cost
|
||||||
getDeliveryCost() {
|
getDeliveryCost() {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const PaymentMethodSelector = ({ paymentMethod, onChange, deliveryMethod, onDeli
|
|||||||
// Handle delivery method changes - auto-switch to stripe when DHL/DPD is selected
|
// Handle delivery method changes - auto-switch to stripe when DHL/DPD is selected
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if ((deliveryMethod === "DHL" || deliveryMethod === "DPD") && paymentMethod === "cash") {
|
if ((deliveryMethod === "DHL" || deliveryMethod === "DPD") && paymentMethod === "cash") {
|
||||||
handlePaymentMethodChange({ target: { value: "stripe" } });
|
handlePaymentMethodChange({ target: { value: "mollie" } });
|
||||||
}
|
}
|
||||||
}, [deliveryMethod, paymentMethod, handlePaymentMethodChange]);
|
}, [deliveryMethod, paymentMethod, handlePaymentMethodChange]);
|
||||||
|
|
||||||
@@ -42,8 +42,22 @@ const PaymentMethodSelector = ({ paymentMethod, onChange, deliveryMethod, onDeli
|
|||||||
description: "Bezahlen Sie per Banküberweisung",
|
description: "Bezahlen Sie per Banküberweisung",
|
||||||
disabled: totalAmount === 0,
|
disabled: totalAmount === 0,
|
||||||
},
|
},
|
||||||
{
|
/*{
|
||||||
id: "stripe",
|
id: "stripe",
|
||||||
|
name: "Karte oder Sofortüberweisung (Stripe)",
|
||||||
|
description: totalAmount < 0.50 && totalAmount > 0
|
||||||
|
? "Bezahlen Sie per Karte oder Sofortüberweisung (Mindestbetrag: 0,50 €)"
|
||||||
|
: "Bezahlen Sie per Karte oder Sofortüberweisung",
|
||||||
|
disabled: totalAmount < 0.50 || (deliveryMethod !== "DHL" && deliveryMethod !== "DPD" && deliveryMethod !== "Abholung"),
|
||||||
|
icons: [
|
||||||
|
"/assets/images/giropay.png",
|
||||||
|
"/assets/images/maestro.png",
|
||||||
|
"/assets/images/mastercard.png",
|
||||||
|
"/assets/images/visa_electron.png",
|
||||||
|
],
|
||||||
|
},*/
|
||||||
|
{
|
||||||
|
id: "mollie",
|
||||||
name: "Karte oder Sofortüberweisung",
|
name: "Karte oder Sofortüberweisung",
|
||||||
description: totalAmount < 0.50 && totalAmount > 0
|
description: totalAmount < 0.50 && totalAmount > 0
|
||||||
? "Bezahlen Sie per Karte oder Sofortüberweisung (Mindestbetrag: 0,50 €)"
|
? "Bezahlen Sie per Karte oder Sofortüberweisung (Mindestbetrag: 0,50 €)"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const config = {
|
|||||||
apiBaseUrl: "",
|
apiBaseUrl: "",
|
||||||
googleClientId: "928121624463-jbgfdlgem22scs1k9c87ucg4ffvaik6o.apps.googleusercontent.com",
|
googleClientId: "928121624463-jbgfdlgem22scs1k9c87ucg4ffvaik6o.apps.googleusercontent.com",
|
||||||
stripePublishableKey: "pk_test_51R7lltRtpe3h1vwJzIrDb5bcEigTLBHrtqj9SiPX7FOEATSuD6oJmKc8xpNp49ShpGJZb2GShHIUqj4zlSIz4olj00ipOuOAnu",
|
stripePublishableKey: "pk_test_51R7lltRtpe3h1vwJzIrDb5bcEigTLBHrtqj9SiPX7FOEATSuD6oJmKc8xpNp49ShpGJZb2GShHIUqj4zlSIz4olj00ipOuOAnu",
|
||||||
|
mollieProfileKey: "pfl_AtcRTimCff",
|
||||||
|
|
||||||
// SEO and Business Information
|
// SEO and Business Information
|
||||||
siteName: "Growheads.de",
|
siteName: "Growheads.de",
|
||||||
|
|||||||
Reference in New Issue
Block a user