支付成功但无法创建订单react stripe

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

我正在尝试实施条带支付并在我的数据库中创建订单。即使我的条纹付款成功,我也无法在数据库中创建订单。我的实施 - 购物车:

import './ShoppingCart.css';
import {useSelector} from 'react-redux';
import { useState, useEffect } from 'react';
import {useNavigate }from 'react-router-dom';
import { useDispatch } from 'react-redux';
import StripeCheckout from 'react-stripe-checkout';
import logo from '../images/BritonStore.png';
import {userRequest} from '../requestMethods';
import { Link } from 'react-router-dom';
// const KEY = process.env.REACT_APP_STRIPE;

const ShoppingCart = ({id}) => {
const cart = useSelector(state=>state.cart);
const [stripeToken, setStripeToken] = useState(null);
const history = useNavigate();

const user = JSON.parse(localStorage.getItem("persist:root"))?.user;
const currentUser = user && JSON.parse(user).currentUser;
const TOKEN = currentUser?.accessToken;
// console.log(TOKEN)
const width = window.innerWidth;

const onToken = (token) => {
    setStripeToken(token);
  };

useEffect(()=>{
    const makeRequest = async ()=>{
        try{
            const res = await userRequest.post("/checkout/pay", {
                tokenId:stripeToken.id,
                amount: cart.total,
            });
            console.log(res)
            history('/success', {stripeData: res.data, products: cart});
        }catch(err){
            console.log(err)
        }
    };
    stripeToken && makeRequest();
}, [stripeToken, cart.total, history])

return (
    <div>
        {cart.products.length === 0 && width < 451 ? 
        <div className='emt-cart'>
            <div className="emt-wrapper">
                <h2 className="emt-header">Your Bag is Empty.</h2>
                <div id="sc-empty-cart-animated-image" type="image/svg+xml" data="https://m.media-amazon.com/images/G/02/cart/empty/animated/rolling-cart-desaturated._CB405717979_.svg">
                <img alt="" src="https://m.media-amazon.com/images/G/02/cart/empty/animated/cart-fallback-desaturated._CB405717979_.svg"/>
                </div>
            </div>
        </div> 
        : 
        cart.products.length === 0 && width > 451 ?         
        <div className="emt-pc-wrapper">
            <div className='emt-pc'>
                <img src="https://m.media-amazon.com/images/G/02/cart/empty/kettle-desaturated._CB424695504_.svg" alt="" />
                <div className="emt-pc-text">
                    <h2>Your Bag is Empty</h2>
                    <Link to='/store'>Continue Shopping</Link>
                </div>
            </div>
        </div>
        :
        <div className='cartscreen'>
            <div className='cartscreen-title'>
                <h2>Review your bag.</h2>
                <p>Free delivery and free returns</p>
            </div>

{cart.products.map(product=>(
            <div className='cart' key={cart.products.id}>
                <div className='image'>
                    <img src={product.image} key={product._id}/>
                </div>
                <div className='details'>
                    <div className='title'>
                        <h3>{product.title}</h3>
                        <p>Product ID: {product._id}</p>
                    </div>
                    <div className='quantity'>
                        <p>Quantity: {product.quantity}</p>
                    </div>
                    <div className='total-price'>
                        <p>{product.price*product.quantity}$</p>
                        <p>Remove</p>
                    </div>
                </div>
            </div>
       ))}

            <div className='total'>
                <div className='left'>
                    <p>Subtotal</p>
                    <p>Shipping</p>
                </div>
                <div className='right'>
                    <p> {cart.total} $</p>
                    <p>Free</p>
                </div>
            </div>
            <div className='f-total'>
                <h4>Total</h4>
                <h4> {cart.total} $</h4>
            </div>
            <div className='checkout'>
                <div className='method'>
                    <h3>How would you like to checkout ?</h3>
                </div>
            </div>
                <div className='method-cards'>
                    <div className='card'>
                        <h2>Proceed To Checkout</h2>
                        {TOKEN ? <StripeCheckout
                        name='Store'
                        image={logo}
                        billingAddress
                        shippingAddress
                        description={`Your total is $${cart.total}`}
                        amount={cart.total*100}
                        token={onToken}
                        stripeKey={"pk_test_51KLN11ITl57zrxjuYSYut39BpN1qKSqcUWCksXqFXJU95FxSIei4O4Lfb4BrH4Rc7hWN7rZRy7sbz2J7QCC08QSf00AwpDVnBB"}
                        >
                        <button className='btn-payment'>Pay Now!</button>
                        </StripeCheckout> : <p className='login-wrng'>Please <Link to='/login'>Login</Link> to continue payment</p>}
                        {TOKEN ? <p className='payment-methods'>We accept payments from PayPal, Visa, MasterCard</p> : null}
                    </div>
                </div>
        </div>}

    </div>
  )
}

export default ShoppingCart

成功屏幕/创建订单屏幕:我相信问题出在

[  const data = location.state.stripeData;
const cart = location.state.cart;]
。屏幕变为空白,控制台显示 “无法读取未定义 stripeData 的属性。” location = useLocation() 返回状态 null。

import React, {useState, useEffect} from 'react';
import { useLocation } from 'react-router';
import {useSelector} from 'react-redux';
import { userRequest } from '../requestMethods';

const Success = () => {
  const location = useLocation();
  const data = location.state.stripeData;
  const cart = location.state.cart;
  const currentUser = useSelector((state) => state.user.currentUser);
  const [orderId, setOrderId] = useState(null);

  useEffect(() => {
    const createOrder = async () => {
      try {
        const res = await userRequest.post("/orders", {
          userId: currentUser._id,
          products: cart.products.map((item) => ({
            productId: item._id,
            quantity: item._quantity,
          })),
          amount: cart.total,
          address: data.billing_details.address,
        });
        setOrderId(res.data._id);
      } catch(err) {
        console.log(err)
      }
    };
    data && createOrder();
  }, [cart, data, currentUser]);
  return (
    <div>
      {orderId
        ? `Order has been created successfully. Your order number is ${orderId}`
        : `Failed...`}
    </div>
  )
}

export default Success

订购型号-

const mongoose = require('mongoose');

const orderSchema = new mongoose.Schema(
    {
        userId: {type: String, required: true, unique:true},
        products: [
            {
                productId: {type: String},
                quantity: {type: Number, default: 1},
                
            },
        ],
        amount: {type:Number, required:true},
        address: { type: Object, required:true },
        status: {type: String, default: 'pending'},
    }, {timestamps: true}
);

module.exports = mongoose.model('Order', orderSchema);

订购路线-

const Order = require("../models/Order");
const {
  verifyToken,
  verifyTokenAndAuthorization,
  verifyTokenAndAdmin,
} = require("./verifyToken");

const router = require("express").Router();

//CREATE
router.post("/", verifyToken, async (req, res) => {
  const newOrder = new Order(req.body);

  try {
    const savedOrder = await newOrder.save();
    res.status(200).json(savedOrder);
  } catch (err) {
    res.status(500).json(err);
  }
});
node.js reactjs redux stripe-payments payment
2个回答
0
投票

首先,创建 orderRedux.js

import { createSlice } from "@reduxjs/toolkit";

const OrderSlice = createSlice({
  name: "order",
  initialState: {
    orders: [],
    isFetching: false,
    error: false,
  },
  reducers: {
    //Add order
    addOrderStart: (state) => {
      state.isFetching = true;
      state.error = false;
    },
    addOrderSuccess: (state, action) => {
      state.isFetching = false;
      state.orders.push(action.payload);
    },
    addOrderFailure: (state) => {
      state.isFetching = false;
      state.error = true;
    },
  },
});
export const {
  addOrderFailure,
  addOrderStart,
  addOrderSuccess,
} = OrderSlice.actions;
export default OrderSlice.reducer;

然后我们在 apiCalls.js

中创建一个函数来调用 redux
import { userRequest } from "../requestMethods";
import { addOrderFailure, addOrderStart, addOrderSuccess } from "./orderRedux";

export const addOrder = async (order, dispatch) => {
  // console.log(order)
  dispatch(addOrderStart());
  try {
    const res = await userRequest.post("orders", order)
      .then((response) => {
        console.log(response.data);
      }, (err) => {
        console.log(err);
      })
    dispatch(addOrderSuccess(res.data));
  } catch (err) {
    dispatch(addOrderFailure());
  }
};

然后在ShoppingCart脚本中,

const dispatch = useDispatch();

支付成功后调用我们创建的函数addOrder

history('/success', {stripeData: res.data, products: cart});
 let order;
        cart.products.map((item) => {
          order = {
            userId: user._id,
            proudcts: [{ productId: item._id }, { quantity: item.quantity }],
            amount: item.quantity * item.price,
            address: res.data.billing_details.address,
            statusorder: "pending"
          }
        });
        addOrder(order, dispatch);
      } catch { }

在您的 success 脚本末尾,从您的 api 获取请求。 我希望这个解决方案可以帮助你✨


-1
投票

我不知道你是否解决了这个问题,但我确信其他人会发现我的答案是有价值的。从react-router-dom v6开始,useHistory()钩子被useNavigate()取代。您将需要使用 useNavigate() 而不是 useHistory()。所以你的代码将是这样的:

从“react-router-dom”导入{useNavigate}

常量导航= useNavigate()

... 导航(“/成功”,{状态:{数据:res.data})

这是新的方式,我希望你能理解我的解决方案并在你的代码中实现它。

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