Home > database >  How to push the data to firestore after stripe checkout session complete using React js frontend
How to push the data to firestore after stripe checkout session complete using React js frontend

Time:07-01

I am trying to push the checkout basket data to firebase firestore after a stripe checkout session complete using react js node js. the checkout session successfully completed without error. However, there are NO user orders data being push to firebase firestore from the piece of code below:

const { error } = await stripe.redirectToCheckout({
        sessionId
      }).then(()=>{
        db
        .collection('users')
        .doc(user?.uid)
        .collection('orders')
        .doc()
        .set({
         basket: basket,
        //  amount: paymentIntent.amount,
       })
     });

Below is the whole pieces of codes of backend and frontend

Functions/index.js

const functions = require("firebase-functions");
const express=require("express");
const cors=require("cors");
require('dotenv').config({ path: './.env' });
//API
const stripe=require("stripe")('sk_test_51KM...zIP');
//App config
const app=express();
var admin = require("firebase-admin");
var serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});
//middlewares
app.use(cors({origin: true}));
app.use(express.json());
async function createCheckoutSession(req, res) {
  const domainUrl = process.env.WEB_APP_URL;
  const { line_items, customer_email } = req.body;
  // check req body has line items and email
  if (!line_items || !customer_email) {
    return res.status(400).json({ error: 'missing required session parameters' });
  }
  let session; 
  try {
    session = await stripe.checkout.sessions.create({
      payment_method_types: ['card'],
      mode: 'payment',
      line_items,
      customer_email,
      success_url: `${domainUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
      // success_url: '/success?session_id={CHECKOUT_SESSION_ID}',
      cancel_url: `${domainUrl}/canceled`,
      shipping_address_collection: { allowed_countries: ['GB', 'US'] }
    }); 
    res.status(200).json({ sessionId: session.id, });
  } catch (error) {
    console.log(error);
    res.status(400).json({ error: 'an error occured, unable to create session'});
  }}
app.get('/',(req, res)=>res.send('Hello World!'));
app.post('/create-checkout-session', createCheckoutSession);
exports.api=functions.https.onRequest(app);

src/strip-checkout.js

import React, { useContext, useState,useEffect } from 'react';
import { useStripe } from '@stripe/react-stripe-js';
import CheckoutProduct from '../CheckoutProduct';
import { useStateValue } from '../StateProvider';
import { db } from '../firebase';
import { fetchFromAPI } from '../helpers';
import "./stripe-checkout.css";
import { useHistory } from 'react-router-dom/cjs/react-router-dom.min';

const StripeCheckout = () => {
  const history=useHistory();
  const [{basket, user},dispatch]=useStateValue();
  const [email, setEmail] = useState('');
  const [processing,setProcessing]=useState(""); 
  const stripe = useStripe();
  const handleGuestCheckout = async (e) => {
        e.preventDefault();
        setProcessing(true);
        const line_items = basket?.map(item => {
          return {
            quantity: 1,
            price_data: {
              currency: 'usd',
              unit_amount: item.price*100, // amount is in cents
              product_data: {
                name: item.title,
                description: item.material
                images: [item.image[0]],
              }}}})
      const response = await fetchFromAPI('create-checkout-session', {
        body: { line_items, customer_email: user.email },
      })
      const { sessionId } = response;
      const { error } = await stripe.redirectToCheckout({
        sessionId
      }).then(()=>{
        db
        .collection('users')
        .doc(user?.uid)
        .collection('orders')
        .doc()
        .set({
         basket: basket,
       })
     });
      console.log(sessionId);
      if (error) {
        console.log(error);
      }}
  return (
    <form onSubmit={handleGuestCheckout}>
      <div className='submit-btn'>
        <button type='submit' >
        <span>{processing ?<p>Processing</p>:
          "Proceed to Checkout"}</span>
        </button>
      </div>
    </form>
  );
}

export default StripeCheckout;

Since there is no shown any error or warning, how to push the data to firestore after stripe checkout session complete in this case?

CodePudding user response:

Stripe Checkout returns to either a success- or a cancel-URL.

It does not send data to both URLs, except the CHECKOUT_SESSION_ID you may add to it when defining these URLs.

The usual way to get data from Stripe Checkout is to use a Firebase Function Webhook. This Webhook is called by Stripe if a transactions is done, or upon failure etc. This Webhook stores the data in Firebase. I had the same problem and found no other, proper solution than using a Webhook.

https://stripe.com/docs/webhooks

There is also a Firebase Extension providing support for Stripe, including the Webhook. Basically. it will add some collections to Firestore, which you then can query.

https://firebase.google.com/products/extensions/stripe-firestore-stripe-payments

  • Related