Martial Laubier
Martial Laubier

Reputation: 1

Send data to backend JS, after Stripe confirmation URL

I have a problem to send data, in this case on the delivery address, the products purchased, the date of purchase, the user who made this purchase. I have a problem with when to send this data and how? I use the stripe api to realize the payment, everything works the user is redirected on the stripe link with his session, and pay according to the items in his cart. But my checkout data is lost. The ideal would be that when stripe confirms the purchase and thus redirects on the url of success, which is the case, and well the quoted data are transferred. So I have this code:

HTML CHECKOUT

    <div class="form">
        <p class="text">Adresse de livraison</p>

        <input type="text" id="address" placeholder="adresse">
        
        <div class="two-input-container">
            <input type="text" id="city" placeholder="ville">
            <input type="number" id="state" placeholder="code postale">
        </div>
        <input type="text" id="landmark" placeholder="informations complémentaire">
    </div>

CHECKOUT JS

window.onload = () => {
    if(!sessionStorage.user){
        location.replace('/login')
    }

    if(location.search.includes('payment=done')){
        let items = [];
        localStorage.setItem('cart', JSON.stringify(items));
        showFormError("order is placed");
    }

    if(location.search.includes('payment_fail=true')){
        showFormError("Une erreur est survenue, merci de réessayer");
    }
}

// select place order button
const placeOrderBtn = document.querySelector('.place-order-btn');

const getAddress = () => {
    // form validation
    let address = document.querySelector('#address').value;
    let city = document.querySelector('#city').value;
    let state = document.querySelector('#state').value;
    let landmark = document.querySelector('#landmark').value;

    if(!address.length || !city.length || !state.length){
        return showFormError("Remplisser tous les champs");
    } else{
        return { address, city, state, landmark }
    }
}
placeOrderBtn.addEventListener('click', () => {
    let cart = JSON.parse(localStorage.getItem('cart'));
    if(cart == null || !cart.length){
        return showFormError("Vous commander aucun article");
    }
    else{
        let address = getAddress();
        
    if(address.address.length){
        // send data to backend
        fetch('/stipe-checkout', {
            method: 'post',
            headers: new Headers({'Content-Type': 'application/json'}),
            body: JSON.stringify({
                items: JSON.parse(localStorage.getItem('cart')),
                address: address,
                email: JSON.parse(sessionStorage.user).email
            })
        })
        .then(res => res.json())
        .then(url => {
            location.href = url;
        })
        .catch(err => console.log(err))
    }
}
})

SERVER index.JS

// stripe payment
let stripeGateway = stripe(process.env.stripe_key);

let DOMAIN = process.env.DOMAIN;

app.post('/stipe-checkout', async (req, res) => {
    const session = await stripeGateway.checkout.sessions.create({
        payment_method_types: ["card"],
        mode: "payment",
        success_url: `${DOMAIN}/success?session_id={CHECKOUT_SESSION_ID}&order=${JSON.stringify(req.body)}`,
        cancel_url: `${DOMAIN}/checkout?payment_fail=true`,
        line_items: req.body.items.map(item => {
            return {
               price_data: {
                   currency: "eur",
                   product_data: {
                       name: item.name,
                       description: item.shortDes,
                       images: item.images
                   },
                   unit_amount: item.price * 100
               },
               quantity: item.item 
            }
        })
    })

    res.json(session.url)
})

app.get('/success', async (req, res) => {
    let { order, session_id } = req.query;

    try{
        const session = await stripeGateway.checkout.sessions.retrieve(session_id);
        const customer = await stripeGateway.customers.retrieve(session.customer);

        let date = new Date();

        let orders_collection = collection(db, "orders");
        let docName = `${customer.email}-order-${date.getTime()}`;

        setDoc(doc(orders_collection, docName), JSON.parse(order))
        .then(data => {
            res.redirect('/checkout?payment=done')
        })

    } catch{
        res.redirect("/404");
    }
})

I've tried to send it before but in fact if someone click to the button to redirect to stripe confirm page, his delivered data, will be stored even if he don't confirm his buy.

Upvotes: 0

Views: 339

Answers (1)

RyanM
RyanM

Reputation: 2960

So when your customers trigger the redirect to Stripe Checkout, the address data you want to retain is present in the req variable in your app.post('/stripe-checkout'?

In that case you can include this data when creating the Checkout Session in the payment_intent_data.shipping parameter. Then this data will be stored on the shipping property of the Payment Intent that the Checkout creates. You can get this data when you retrieve the Checkout Session (either server-side or client-side) by passing payment_intent in the Expand parameter and looking at the payment_intent.shipping.address property on the Checkout session object.

Alternatively, you could have the Checkout Session itself collect shipping address information for you. This would store the address in the shipping_details.address property.

To ensure your integration is able to get the customer's address information I recommend you configure your integration to listen to the checkout.session.completed webhook. That way, even if the customer fails to redirect back to your site, your back-end code will still be able to get the address information.

Upvotes: 1

Related Questions