Netflix Clone with Stripe and Firebase
Need to install firebase on your react app using   npm add firebase
       Setting up Firebase
       Setting up Authentication in Firebase
          (a) In Firebase Website
          (b) In application
       Setting up Stripe Payment
          (a) In the firebase website
          (b) In the Stripe website
          (c) In the React Application
       Setting up Firebase
         Log in to Firebase
         Create new project
         Click on Project Settings
         Click on the website logo
         Ensure that setting up firebase hosting is checked
         Click next and ensure step 3 is done -   sudo npm install -g firebase-tools
         Once done, under the firebase sdk snippet , click on config
Netflix Clone with Stripe and Firebase                                                   1
         Copy the whole config and paste it into a new file called       firebase.js
       Setting up Authentication in Firebase
       (a) In Firebase Website
         Go to the Authentication
         Get Started
         Click on the Email/Password and enable it
       (b) In application
         Navigate/Create new file call      firebase.js
         In the   firebase.js
            import firebase from 'firebase'
            //API KEY FROM FIREBASE
            //const firebaseConfig = ...
            const firebaseapp = firebase.initialiseApp(firebaseConfig);
            const db = firebaseapp.firestore() //<------- for the database
            const auth = firebase.auth() //<------------- for the authentication
            export {auth}
            export default db
         In your js file that contains the sign in component
           (a) Two things to do:
Netflix Clone with Stripe and Firebase                                                   2
                Register your account
                   //Need to ensure that states have been declare to point to the input field.
                   const register = (e) => {
                     e.preventDefault();
                       auth.createUserWithPasswordAndEmail(
                       //Pass in the the state or ref that contains the EMAIL and PASSWORD value
                       )
                       .then(() => {}
                       .catch((error) => {
                         alert(error.message);
                       });
                Sign in
                   const signIn = (e) => {
                     e.preventDefault();
                       auth.signInWithEmailAndPassword(
                       //Pass in the the state or ref that contains the EMAIL and PASSWORD value
                         )
                         .then(() => {}
                         .catch((error) => {
                           alert(error.message);
                         });
                   }
         To ensure persistence (doesnt log u out everytime u refresh unless u activate the signout)
              In your   app.js
            const user = useSelector(selectUser);
            const dispatch = useDispatch();
            //For logging in and logging out
            //Need for the retention of logged in info
            useEffect(() => {
              //acts like a listerner so it listens to any authenticated state change
              //if log in and refresh, it will store it to your local memory
              const unsubscribe = auth.onAuthStateChanged((userAuth) => {
                if (userAuth){
                  //logged in
                  dispatch(login({
                    uid: userAuth.uid,
                    email: userAuth.email,
                  }))
                } else {
                  //logged out
                  dispatch(logout())
                }
              });
              //cleaning up
              //if the component was to unmount, we don't want to duplicate another listerner
              return unsubscribe
            }, [dispatch, auth])
         We will then implement redux, new file call        userslice.js
            import { createSlice } from '@reduxjs/toolkit';
            export const userSlice = createSlice({
              name: "user",
              initialState: {
                user: null,
              },
              // The `reducers` field lets us define reducers and generate associated actions
              // In here the login and logout are called actions
              // These actions can then be dispatch and it will do the appropriate behavoir
              reducers: {
                login: (state, action) => {
                  state.user = action.payload;
                },
                logout: (state) => {
Netflix Clone with Stripe and Firebase                                                                  3
                   //resetting back the user to null
                   state.user = null;
                 },
               },
             });
             export const { login, logout } = userSlice.actions;
             // The function below is called a selector and allows us to select a value from
             // the state. Selectors can also be defined inline where they're used instead of
             // in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`
             export const selectUser = (state) => state.user.user;
             export default userSlice.reducer;
         To sign out, we can just do an        onClick   function on a sign out button, and pass   auth.signOut()   .
       Setting up Stripe Payment
       (a) In the firebase website
           Cloud Firestore >> Create database >> Start in test mode
           Go to the extensions table in the navbar of firebase website (all the way below)
           Install stripe
               Under the Configure Extension tab, ensure sync is allowed
               To input the stripe key, go to the stripe website and sign in.
                   Reveal your test key.
                   Paste that Secret Key
           Setting up the rules
               Go to Cloud Firestore >> Rules tab
               https://github.com/stripe/stripe-firebase-extensions/tree/next/firestore-stripe-subscriptions ⟶ Explore this
               website
               Under POSTINSTALL.md
               Copy the rules >> paste >> Publish
             rules_version = '2';
             service cloud.firestore {
               match /databases/{database}/documents {
                 match /${param:CUSTOMERS_COLLECTION}/{uid} {
                   allow read: if request.auth.uid == uid;
Netflix Clone with Stripe and Firebase                                                                                        4
                        match /checkout_sessions/{id} {
                          allow read, write: if request.auth.uid == uid;
                        }
                        match /subscriptions/{id} {
                          allow read: if request.auth.uid == uid;
                        }
                    }
                    match /${param:PRODUCTS_COLLECTION}/{id} {
                      allow read: if true;
                        match /prices/{id} {
                          allow read: if true;
                        }
                        match /tax_rates/{id} {
                          allow read: if true;
                        }
                    }
                }
            }
          Once stripe extension is installed, go to Configure Stripe Webhooks
          Get the unique url and note the events
       (b) In the Stripe website
          In the dashboard, go to the tab call webhooks
          Add Endpoint
                Endpoint url
                Events to send
          Once ended, get the Signing Secret key
                Go back to the firebase website >> extensions tab >> Manage Stripe >> Reconfigure Extension
                Under Stripe webhook secret input field, paste that secret key
Netflix Clone with Stripe and Firebase                                                                        5
           Create Products
               On the left hand side, go to the Products tab >> Add Product
           On the left hand side, go to settings >> Scroll down under Business Setting >> Branding
               Allow u to customise the payment page
           Under Product Setting >> Customer Portal ⟶ Follow instructions from here
           Must ensure that there is a business name
       (c) In the React Application
           Under the component where you want to link it to the stripe webpage
         const [products, setProducts] = useState([])
           const user = useSelector(selectUser)
          /* To retrieve the subscription data of the user */
          const [subscription, setSubscription] = useState(null)
          useEffect(()=> {
              db.collection("customers")
                .doc(user.uid)
                .collection('subscriptions')
                .get()
                .then(querySnapshot => {
                  /* querySnapshot represents the result of a query */
                  /* loop through forEach subscriptions and retrieve the role attribute, current period start and end */
                  querySnapshot.forEach( async subscription => {
                    setSubscription({
                      role: subscription.data().role,
                      current_period_end: subscription.data().current_period_end.seconds,
Netflix Clone with Stripe and Firebase                                                                                     6
                      current_period_start: subscription.data().current_period_start.seconds,
                    });
                  });
                });
          }, [])
          /* fetch the plans from the database */
          /* The documents can be accessed as an array via the docs property or enumerated using the forEach method. */
          /* https://console.firebase.google.com/project/netflix2-clone-e95d8/firestore/data~2Fproducts~2Fprod_JT3hRI7rwmgJfh */
          /* The 'products' and 'active' attribute is displayed in the link above */
          useEffect(() => {
                db.collection('products')
                .where('active', '==', true)
                .get()
                .then((querySnapshot) => {
                  const products = {};
                  querySnapshot.forEach(async (productDoc) => {
                    products[productDoc.id] = productDoc.data();
                    const priceSnap = await productDoc.ref.collection('prices').get();
                    priceSnap.docs.forEach((price) => {
                      products[productDoc.id].prices = {
                        priceId: price.id,
                        priceData: price.data(),
                      };
                    });
                  });
                  setProducts(products);
                });
          },[]);
          /* function to render the checkout/paying screen */
          const loadCheckout = async (priceId) => {
            //pulling the user from the redux store
            const docRef = await db
              .collection('customers')
              .doc(user.uid)
              .collection("checkout_sessions")
              .add({
                price: priceId,
                success_url: window.location.origin,
                cancel_url: window.location.origin,
              })
               docRef.onSnapshot(async(snap) => {
                 const {error, sessionId} = snap.data();
                if (error){
                  //show an error to your customer and inspect your Cloud Function logs in the Firebase console
                  alert(`An error occured: ${error.message}`)
                }
                if (sessionId){
                     //We have a session, lets redirect to Checkout
                     //Initialise stripe
                     const strip = await loadStripe('pk_test_51IpNyNFws4ncZVjIE5PzlqMhXPP780p2H9hetmUSWL48bAnpSxUwzAmikcBNhORCyfolUWnt8dAs4gvlMEv
                     strip.redirectToCheckout({sessionId});
                 }
               });
          };
Netflix Clone with Stripe and Firebase                                                                                                              7