Home > Software engineering >  Which condition is correct to add?
Which condition is correct to add?

Time:12-14

I'm doing a small project in Node and React And I'm building a payment system with the help of Stripe Now everything works fine I have only one small problem I want at the end of the process to update the quantity in the database the problem is that I can't make the right condition to do it and I must a condition Because if I don't set a condition as soon as I activated Stripe and got to the payment page, even if I didn't pay and did a return to the previous page, my quantity is updated

I add here the code I try to implement

exports.getCheckoutSessionBook = async (req, res, next) => {
    const book = req.body.bookID[0]
    console.log(book._id)
    const quantity = req.body.quantityBooks
    if (book.quantity < quantity) return next(new AppError(`there is only ${book.quantity} in stuck `))

    if (book.quantity <= 0) return next(new AppError(`this book is over please try another book `))


    const session = await stripe.checkout.sessions.create({
        payment_method_types: ['card'],
        success_url: `http://127.0.0.1:3001`,
        cancel_url: `http://127.0.0.1:3001/account`,
        customer_email: req.user.email,
        client_reference_id: req.user.id,
        line_items: [{
            price_data: {
                currency: 'usd',
                product_data: {
                    name: book.title,
                    description: book.description,
                    images: [book.image],

                },
                unit_amount: book.price * 100,

            },
            quantity: quantity,


        }],
        mode: 'payment',



    });

    res.status(200).json({
        status: 'suceess',
        session
    })
//here is my problem
    if (res.status == 200) {
        console.log(321)
        const doc = await Book.findByIdAndUpdate(book._id, { $inc: { quantity: - quantity } }, {
            new: true,
            runValidators: true
        })
        console.log(333)
    }

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

CodePudding user response:

The code you shared calls the Create Checkout Session API first. This creates a Session that indicates what you are trying to sell to your Customer. At that point, no payment has been taken yet though. After that call, you seem to immediately increase the quantity in your database, before the payment happened.

There's no condition you can add here because the payment will happen later so you need to delete that part of the code or move it elsewhere entirely.

After the Checkout Session is created, you get the url property back in the response. That is the URL that you should redirect your customer to in the browser. There, they'll see Checkout's UI and decide if they want to pay.

What you should do, is listen for the checkout.session.completed Event that will be sent to your webhook endpoint when a Session gets paid/completed successfully. At that point, you can update the quantity in your database.

Stripe has a detailed documentation on fulfillment with Checkout in this doc.

CodePudding user response:

I must confess I'm not familiar with the Stripe API, but your approach to what is essentially a distributed transaction is giving me anxiety.

Your system needs assume it may crash at any point and still be able to any transaction.

Basically you need a series of interconnected backend systems using a ledger system in the database. A ledger is an ordered set of actions taken on a transaction that allows you to see what has happened so far and pick up the transaction from where it was left.

Basic steps in an order transaction could be:

  1. Create the order.
  2. Allocate the inventory to the order.
  3. Get an ID from the payment provider and associate it with the order.
  4. Send the customer to complete the payment.
  5. When payment is complete move the order ready for shipping.
  6. Handle shipping.
  7. Close the order and update inventory.

Some notes: Inventory is not changed up/down for every order open/cancelled/closed inventory is updated once the item is actually shipped. Inventory for sale is inventory on hand minus any inventory allocated to orders.

Note also that if your system crashes (or the client disconnects) at any point you can reconcile the orders. Failure after step 1 -> close the order. Failure after step 2 -> close the order (inventory becomes immediately available since it is no longer allocated). Failure after step 3 -> check the status of the payment using the session ID with the payment provider and either close the order or continue to step 4. etc.

Final note: whether orders fails if inventory cannot be allocated to orders varies based on whether you can order more inventory or not.

If all this sounds complex it's because it is. Making an online store front system is not a weekend project.

  • Related