在线支付后回复消息

问题描述 投票:0回答:1

我为 Ecomm 创建了这个小型 React 项目。当我点击“货到付款”,然后点击“付款”时,一切都很顺利——订单完成,发票创建,购物车清空。但是,到了网上支付的时候,就回到首页了,没有清购物车,也没有创建发票

查出页面:

import React, { useState, useEffect } from 'react';
import { useMutation, useLazyQuery } from '@apollo/client';
import { CREATE_ORDER, CREATE_ADDRESS, GET_USER_ADDRESSES, GET_DISCOUNT, CREATE_ORDER_DETAIL,  } from './queries';
import { useNavigate } from 'react-router-dom';
import { useCart } from './CartContext';
import './client.css';
import AddressList from './AddressList';
import OrderCompleteModal from './OrderCompleteModal';
import Modal from './Modal';
import { loadStripe } from '@stripe/stripe-js';


function CheckoutPage() {
    const { cart, clearCart } = useCart();
    const [createOrder] = useMutation(CREATE_ORDER);
    const [createAddress] = useMutation(CREATE_ADDRESS);
    const [getDiscount] = useLazyQuery(GET_DISCOUNT);
    const [getUserAddresses, { data: addressesData, loading, error }] = useLazyQuery(GET_USER_ADDRESSES);
    const [createOrderDetail] = useMutation(CREATE_ORDER_DETAIL);
    const navigate = useNavigate();

    const [selectedAddress, setSelectedAddress] = useState(null);
    const [address, setAddress] = useState({
        AddressName: '',
        AddressPhone: '',
        AddressCountry: '',
        AddressCity: '',
        AddressArea: '',
        AddressStreet: '',
        AddressHouseNum: ''
    });
    const [discountCode, setDiscountCode] = useState('');
    const [discountAmount, setDiscountAmount] = useState(0);
    const [isAddingAddress, setIsAddingAddress] = useState(false);
    const [showModal, setShowModal] = useState(false);
    const [orderId, setOrderId] = useState(null);
    const [addressesList, setAddressesList] = useState([]);
    const [errorMessage, setErrorMessage] = useState('');
    const [paymentMethod, setPaymentMethod] = useState('');

    const stripePromise = loadStripe('pk_test_51P5UiCRtvqzaEbEbROHSyEASzLd3qsZlhZrTvnQNBLErArOalM7iu20FkoSJqDL1Jet579YHk4c0jksIMFqTJC7n00aTNDFkNG');


    useEffect(() => {
        const userId = localStorage.getItem('userId');
        if (userId) {
            getUserAddresses({ variables: { userId: parseFloat(userId) } });
        }
    }, [getUserAddresses]);

    useEffect(() => {
        if (addressesData) {
            setAddressesList(addressesData.getUserAddresses);
        }
    }, [addressesData]);

    const handleInputChange = (e) => {
        const { name, value } = e.target;
        setAddress({ ...address, [name]: value });
    };

    const handleDiscountCodeChange = (e) => {
        setDiscountCode(e.target.value);
    };

    const applyDiscount = async () => {
        try {
            const { data } = await getDiscount({ variables: { Dcode: discountCode } });
            if (data && data.getDiscountByCode && data.getDiscountByCode.Dactive) {
                setDiscountAmount(data.getDiscountByCode.Damount);
            } else {
                setDiscountAmount(0);
            }
        } catch (error) {
            console.error('Discount application error:', error);
        }
    };

    const subtotal = cart.reduce((acc, item) => acc + (item.price * (item.quantity || 1)), 0);
    const taxRate = 0.05;
    const tax = subtotal * taxRate;
    const total = subtotal + tax - discountAmount;
    




    const handleCheckout = async () => {
        console.log("Checkout initiated");
        const userId = localStorage.getItem('userId');
        
        // Basic validation
        if (!userId || total <= 0) {
            setErrorMessage('Error: Invalid user ID or total amount');
            console.error('Error: Invalid user ID or total amount');
            return;
        }
    
        if (!selectedAddress) {
            setErrorMessage('You must select or add an address to continue the order.');
            return;
        }
    
        setErrorMessage('');
        
        try {
            const totalInCents = Math.round(total * 100); // Convert total to cents
            console.log("Creating order with total:", totalInCents);
    
            const { data: orderData } = await createOrder({
                variables: {
                    userId: parseInt(userId, 10),
                    total: totalInCents,
                },
            });
    
            const newOrderId = orderData.createOrder.id;
            console.log("Order created with ID:", newOrderId);
    
            // Create order details
            for (const item of cart) {
                await createOrderDetail({
                    variables: {
                        order_id: newOrderId,
                        product_id: item.id,
                        quantity: item.quantity || 1,
                        price: Math.round(item.price * 1.100),
                    },
                });
            }
            
            setOrderId(newOrderId);
            console.log("Order details created");
    
            if (paymentMethod === 'cash') {
                setShowModal(true);  
                clearCart();
                return; 
            }
    
            // Handle online payment
            if (paymentMethod === 'online') {
                const stripe = await stripePromise;
            
                const response = await fetch('http://localhost:3001/api/create-checkout-session', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({ amount: totalInCents }),
                });

            
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
            
                const { id } = await response.json();
            
                // Redirect to Stripe checkout
                const { error } = await stripe.redirectToCheckout({ sessionId: id });
                if (error) {
                    console.error('Stripe redirect error:', error);
                    setErrorMessage('Failed to redirect to payment. Please try again.');
                } else {
                    clearCart(); // Clear cart immediately if you want to do that
                }
            }
            
        } catch (error) {
            console.error('Checkout error:', error);
            setErrorMessage('Failed to create the order or proceed with payment. Please try again.');
        }
    };
    
    
    
    
    
    
    
    
    
    
    const handleBackToHomepage = () => {
        navigate('/');
        setShowModal(false);
    };

    const handleViewInvoice = () => {
        if (orderId) {
            navigate(`/invoice/${orderId}`);
        } else {
            console.error('Order ID is not set');
        }
    };

    const handleCloseAddressForm = () => {
        setIsAddingAddress(false);
        setAddress({
            AddressName: '',
            AddressPhone: '',
            AddressCountry: '',
            AddressCity: '',
            AddressArea: '',
            AddressStreet: '',
            AddressHouseNum: ''
        });
    };

    const handleSaveAddress = async () => {
        const userId = localStorage.getItem('userId');
        if (!userId) {
            console.error('User ID is not available');
            return;
        }
    
        try {
            await createAddress({
                variables: { user_id: parseInt(userId, 10), ...address },
            });
    
            setAddress({
                AddressName: '',
                AddressPhone: '',
                AddressCountry: '',
                AddressCity: '',
                AddressArea: '',
                AddressStreet: '',
                AddressHouseNum: ''
            });
            setIsAddingAddress(false);
            getUserAddresses({ variables: { userId: parseFloat(userId) } });
        } catch (error) {
            console.error('Address creation error:', error);
        }
    };

    return (
        <div className="checkout-page">
            {showModal && (
                <OrderCompleteModal 
                    onClose={handleBackToHomepage} 
                    onViewInvoice={handleViewInvoice}
                    selectedAddress={selectedAddress} 
                    cart={cart}
                    orderId={orderId}
                />
            )}
            {isAddingAddress && (
                <Modal isOpen={isAddingAddress} onClose={handleCloseAddressForm}>
                    <div className="modal-content">
                        <div className="modal-header">
                            <h3>Add New Address</h3>
                            <button className="modal-close" onClick={handleCloseAddressForm}>&times;</button>
                        </div>
                        <div className="modal-body">
                            <div className="address-form">
                                {['AddressName', 'AddressPhone', 'AddressCountry', 'AddressCity', 'AddressArea', 'AddressStreet', 'AddressHouseNum'].map(field => (
                                    <input 
                                        key={field} 
                                        type="text" 
                                        name={field} 
                                        placeholder={field.replace(/Address/, '')}
                                        value={address[field]} 
                                        onChange={handleInputChange} 
                                    />
                                ))}
                            </div>
                            <div className="form-actions">
                                <button className="button save-address" onClick={handleSaveAddress}>Save Address</button>
                                <button className="button cancel" onClick={handleCloseAddressForm}>Cancel</button>
                            </div>
                        </div>
                    </div>
                </Modal>
            )}
            <div className="checkout-container">
                <div className="left-panel">
                    <div className="panel address-panel">
                        <h2>Select Address</h2>
                        {loading && <p>Loading addresses...</p>}
                        {error && <p className="error-message">Error loading addresses: {error.message}</p>}
                        {addressesList && (
                            <AddressList 
                                addresses={addressesList} 
                                onSelectAddress={(id) => setSelectedAddress(id)} 
                            />
                        )}
                        <button className="button add-address" onClick={() => setIsAddingAddress(true)}>Add Address</button>
                        {errorMessage && <p className="error-message">{errorMessage}</p>}
                    </div>
                    <div className="panel payment-panel">
                        <h2>Select Payment Method</h2>
                        <div className="payment-methods">
                            <label>
                                <input 
                                    type="radio" 
                                    name="payment" 
                                    value="cash" 
                                    onChange={() => setPaymentMethod('cash')} 
                                    checked={paymentMethod === 'cash'}
                                />
                                Cash on Delivery (+$10)
                            </label>
                            <label>
                                <input 
                                    type="radio" 
                                    name="payment" 
                                    value="online" 
                                    onChange={() => setPaymentMethod('online')} 
                                    checked={paymentMethod === 'online'}
                                />
                                Online Payment
                            </label>
                        </div>
                    </div>
                </div>
                <div className="right-panel">
                    <div className="panel cart-panel">
                        <h2>Shopping Cart</h2>
                        <ul className="cart-items">
                            {cart.map(item => (
                                <li key={item.id} className="cart-item">
                                    <span className="item-name">{item.Pname}</span>
                                    <span className="item-price">${item.price.toFixed(2)}</span>
                                    <span className="item-quantity">x {item.quantity || 1}</span>
                                </li>
                            ))}
                        </ul>
                        <div className="order-summary">
                            <h3>Order Summary</h3>
                            <div className="summary-row"><span>Subtotal:</span><span>${subtotal.toFixed(2)}</span></div>
                            <div className="summary-row"><span>Tax:</span><span>${tax.toFixed(2)}</span></div>
                            <div className="summary-row"><span>Discount:</span><span>-${discountAmount.toFixed(2)}</span></div>
                            <div className="summary-row total"><span>Total:</span><span>${total.toFixed(2)}</span></div>
                        </div>
                        <div className="discount-code">
                            <input 
                                type="text" 
                                placeholder="Discount Code" 
                                value={discountCode} 
                                onChange={handleDiscountCodeChange} 
                            />
                            <button className="button apply-discount" onClick={applyDiscount}>Apply</button>
                        </div>
                        <button className="button checkout-button" onClick={handleCheckout}>Continue to Payment</button>
                    </div>
                </div>
            </div>
        </div>
    );
}

export default CheckoutPage;

这里弹出窗口:

import React from 'react';
import { useMutation } from '@apollo/client';
import { CREATE_INVOICE } from './queries'; // Adjust import as necessary
import './client.css'; // Import your CSS for styling
import { useNavigate } from 'react-router-dom'; // Import useNavigate

const OrderCompleteModal = ({ onClose, selectedAddress, orderId  }) => {
    const [createInvoice] = useMutation(CREATE_INVOICE);
    const navigate = useNavigate(); // Initialize navigate

    const handleCreateInvoice = async () => {
        try {
            const userId = localStorage.getItem('userId');
            const addressId = selectedAddress; // Ensure this is set
    
            // Debugging logs
            console.log("User ID:", userId);
            console.log("Address ID:", addressId);
            console.log("Order ID:", orderId);
            
    
            if (!userId || !addressId || !orderId ) {
                throw new Error("Missing required parameters");
            }
    
            const { data } = await createInvoice({
                variables: {
                    userId: parseInt(userId, 10),
                    addressId: parseInt(addressId, 10),
                    orderId: parseInt(orderId, 10),
                },
            });
    
            if (data) {
                console.log('Invoice created successfully');
                // Navigate to the invoice page
                navigate(`/invoice/${orderId}`);
            }
        } catch (error) {
            console.error('Error creating invoice:', error);
        }
    };
    
    return (
        <div className="modal-overlay">
            <div className="modal-content">
                <h2>Order Complete</h2>
                <p>Your order has been successfully placed!</p>
                <div className="modal-buttons">
                <button onClick={() => {
                        handleCreateInvoice(); // Create the invoice
                    }}>
                        View Invoice 
                    </button>
                    
                </div>
            </div>
        </div>
    );
};

export default OrderCompleteModal;

我尝试了不止一种解决方案,所有的解决方案在线支付后都不显示弹窗

reactjs stripe-payments
1个回答
-1
投票

您所描述的问题可能会出现,因为在线支付流程依赖于通过 Stripe 的 redirectToCheckout 进行重定向,一旦用户重定向到 Stripe 结帐页面,处理购物车清算和发票创建的代码可能无法正确触发。 对于在线支付,一旦用户被重定向到 Stripe 的结帐页面,后端通常需要确认付款并处理付款后操作,例如创建发票和清理购物车。这个逻辑应该放在你的服务器上,而不是放在前端代码中,因为重定向后,前端不会自动知道支付是否成功。 可能会有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.