10 hours 19 minutes 31 seconds
๐ฌ๐ง English
Speaker 1
06:00:00
Other rooms to test out the functionality. Let's see if our filter works. So a basic room, maybe this 1, and it doesn't have a discount. So if we want to stay for, you know, 2 days, the room should be 600.
Speaker 1
06:00:17
So because the unit price is 300. So everything is OK. Now we can work on, before we work on the booking feature, let's just test that when we call these functions, to create a booking, that we are getting the correct values. So once we click on this function, we are displaying the values that we need to create a booking.
Speaker 1
06:00:41
So we don't have the API yet. So for sanity studio, we are going to be creating all of that so what we can do first is to just do some validation so if there is no check-in date or if there is no checkout date then we're gonna return a toast dot error and then we can just say please provide check-in slash checkouts dates like this okay and let's also check So now we're gonna check if the check-in date is greater than the checkout date. So if that's the case we're gonna return toast.error and we're gonna tell the user please choose a valid check in period like this okay so after this check, so this other check here, we are going to calculate number of days again. So const numberOfDays and numberOfDays is going to be called to a function that would calculate the number of days so you can have this calc number look at just a calc num days like this and you already have the function.
Speaker 1
06:02:23
So I'm just going to copy this function. You know, we can pass it via props, but let's just define here. And I'll just get calcNormDays. And here, rather than return 0, I'll just return.
Speaker 1
06:02:40
And here we have, we get a time difference like this we get a number of days and we return So here we just calculate number of days and next we can get the hotel room slog and the hotel room slog is going to be the room.slog.current And next, we can now integrate Stripe. So Before we integrate Stripe, I want to talk about middlewares. But before we get to middlewares, I also want to make sure that we have the API from Sanity Studio ready to help us to create a booking. In our leaps, in our APIs folder, now we're going to export this.
Speaker 1
06:03:39
Export this constant and then we can call it createBooking, like this, which is going to be equal to this async function, like this. Here, we are going to receive properties that we're going to use to create a booking. These properties is going to be of type. So we don't have this type yet.
Speaker 1
06:04:10
What we can call this createBookingDTO, which stands for data transfer objects. Where do we have our models, rooms? So do we put it in here? I'm just going to put it in here, because it's related to a room, even though it's now related to creating a room.
Speaker 1
06:04:34
Okay, and I'm going to export this type, createBookingDTO, which is going to be equal to this function. To create a booking, we need the user, which is of type string, so the user ID. We need the hotel room, which is also of type string we need a check-in dates and the check-in dates is going to be of type string we also need a check out dates and this is going to be of type string. We need a number of days and the number of days is going to be of type number.
Speaker 1
06:05:14
We need the adults which is going to be of type number. We need the children which is going to be of type number like this. We need the total price. The total price is going to be of type number and then we need the discount which is going to be of type number so we need to spell discount so to confirm if you come over to the schemas, booking.ts, you would see the fields we need.
Speaker 1
06:05:53
So we need the user ID, we need the hotel room ID, so where is it, I will show you past the hotel room ID here. So you see we need the hotel room, we need the check-in date, we need the checkout date, we need the number of days, we need the discounts, we need the adults, children, and the total price. And that's all the fields that are defined in here. Okay.
Speaker 1
06:06:20
So now we are going to import this create booking DTO coming from our models. And in here, We can now assess these properties. So we can assess adults, the check-in dates. We can assess checkout dates.
Speaker 1
06:06:39
We can assess children, discounts, hotel room, number of days, total price, and user. So these are the values we need to create a booking. And then we can have our mutation. And our mutation is going to be an object.
Speaker 1
06:07:00
And we have mutations like this. Mutations is going to be an array. Okay, so an array and here we have an object. So we're going to have a create mutation.
Speaker 1
06:07:15
And to be sure, not to be sure, I just want to show you where I'm getting it from. So let's visit the documentation. So I just googled sanity mutation. And if we click on mutations, just wait for it to load.
Speaker 1
06:07:30
And here, if we click on Create, you see here, you have mutations, you have Creates, and then you pass the values. So this is what we're doing here. So we're using Create Mutation. And then you see the URL.
Speaker 1
06:07:45
So HTTPS, the product ID, API, sanity.io, you give the version, data mutate, and your data set name. OK, so this is the create mutation that we are now currently doing here in the application. We have this create and create is an object. It's an object, so we'll pass on the score type.
Speaker 1
06:08:10
The type of mutation or the type of, Where is it again? Here we come over to our schema booking. The type of schema is booking. So this booking schema, and that's what we have here.
Speaker 1
06:08:25
So apart from the type, we're going to have the user. So remember it needs a user. And here, the underscore type is going to be of type reference. So please make sure there's no typo here else it's not going to you know work as expected and we just have the underscore ref and the underscore ref is going to be this user So it's going to be this user ID here.
Speaker 1
06:08:51
Okay, so after this user, so after this, we are going to have another property, which is a hotel room. So a hotel room like this, and it's going to be an object. So an object where we have the same underscore type and the type is going to be a reference like this And we have the underscore ref which is going to now point to hotel room. Okay so after this hotel room now we can have the other values so the check-in dates, the checkout dates and number of days also adults and then children.
Speaker 1
06:09:41
And then we also have the total price. And then we also have the discounts, like this. And after our mutation, so after this our mutation constant, we can now have our send API request. So we're going to be using Axios.
Speaker 1
06:10:00
I don't know if we have Axios installed, so let's npm install Axios like this. And we're going to get our data, which is going to be equal to await Axios. So I'm just going to restart our server. So here we're going to await Xeos which we need to import.
Speaker 1
06:10:23
So just here I'm gonna import Xeos from Xeos like this and here we're gonna await Xeos.post And the URL is going to be, so we have backtick HTTPS and then we need to go to our project ID, which is going to come from our process.env, and then that will just come to our env, and we're going to copy our next public sanity project ID. I'll paste it here and then we also go to .api.sanity.io and we then specify the API version so v and then 2021 then 21 like this and then we go to slash data slash mutates and then we go to the data set so process dot env and then we come and copy this so nice public sanity data set like this okay so after this we are going to pass another argument. And the data is going to be our mutation. And then we need to pass headers.
Speaker 1
06:11:44
Okay, so here we're going to have headers. And headers is an object like this. Then we have authorization and the authorization is going to be our Biera token. So Biera and then the token is going to come from our process.env and then we have our sanity studio token and that's why it was important to give read and write access because now we want to write to our sanity studio and here we get our data we can now return our data here.
Speaker 1
06:12:23
So we have our endpoints, we have our page setup, now we're going to discuss middlewares. Because we only want authenticated users to be able to book a room. By the way, let's authenticate ourselves. I'll click here And it doesn't load up so I'll just reload our application, you know we restarted our server, so let's be sure It's up and running.
Speaker 1
06:12:56
So it's actually compiling and just compiling our auth page before we refresh our page So let's just wait for it to compile. And as we're saying, we're going to integrate Stripe. So we're going to be integrating Stripe next, but I just want us to discuss about middleware a bit, because we only want users that are authenticated to be able to call the route. Okay so here let's authenticate so I'm just going to authenticate myself using the Google provider.
Speaker 1
06:13:40
And I should be authenticated. OK, so we are authenticated. And we can come back to a room. So any room we do.
Speaker 1
06:13:52
And if we are not authenticated, we don't want the user to go on and book a hotel room. So we don't want this book now to actually make a call. Okay, so let's discuss middlewares now and the way middlewares work. If we come here, so we come to the root of our source folder.
Speaker 1
06:14:17
Yeah, and we create a file called middleware.ts like this and we just need to export defaults like this And then we're going to export this from next-auth, at least next-auth middleware, forward slash middleware. Now with just this line of code, we are going to be blocking all our pages from requests. So we don't have a way to manually log out so we can't see this working in action because we are currently authenticated. But if we are not authenticated we would not have been able to visit this page.
Speaker 1
06:15:01
We don't have the ability to log out yet, so we can't test our functionality, but we get this page cannot be found. OK. So we want to block 2 pages. I want to block 2 routes, actually.
Speaker 1
06:15:18
So I want to block the user profile route, and I also want to block the API route. So I'm going to export the config, which is going to be equal to this object. And this object takes in the matcher. This matcher can be a string, it can be a reject expression, or it can be an area of path.
Speaker 1
06:15:41
On a block, request going to slash users, and then slash the user route like this. Any request going to slash users and then any other route is going to be protected if the user is not authenticated. Same I want to do for our API folder. Request going to slash API, slash and then the path like this is not going to be allowed to pass unless the user is authenticated.
Speaker 1
06:16:15
So now we have this in place, we can now work on our to make sure that we integrate our Stripe payment. To integrate Stripe in our project, first we need to install the Stripe package. I'm going to quit the development server And we are going to start from the back end route. So npm install stripe like this.
Speaker 1
06:16:36
And this is going to go on to install the stripe library. And if we come up to our folder, and in our app, leaves and here, not here, sorry, channel app. And we have where is it our API folder. And here we're going to create a new route for stripe so let's have our stripe route so we have stripe and here we have the stripe.ts so this is our stripe route And let me just restart our server here.
Speaker 1
06:17:09
Okay, so what's the first thing we need to do? Let's have this stripe constants. So stripe is going to be equal to a new instance of stripe. Yep, so we're going to import this stripe from this stripe here.
Speaker 1
06:17:23
And this stripe, this new stance is going to need an API key. Alright, so we don't have that yet, we're going to get it in a second. But we can already reference this so process dot env. And we can call it stripe underscore secret and underscore key like this.
Speaker 1
06:17:44
Okay, we're still having error. We can say a string here. And the other is an object. So a config.
Speaker 1
06:17:51
And here we're going to pass the API version. And it already has an API version. So this API version. So let's get our secret key.
Speaker 1
06:18:01
So our Stripe secret key, if you come to your browser, and here, this is the Stripe dashboard, you already should create an account for Stripe and then you come over to your dashboard, you see that you have to be in test mode and even to activate, to go live you need to activate your account. So in test mode you come here so you see we have our publishable key and we have our secret key but for now we need our secret key so I'm going to copy this secret key And we come to application here in our env. First, I'm just going to paste in the secret key here. And for the value for the key, I'm going to copy this and use here.
Speaker 1
06:18:45
So our Stripe secret key is going to be equal to this key we just copied. OK, so let's save this. And next, we are going to have our function. So let's export a const function, async function, like this.
Speaker 1
06:19:03
We're going to call it post. This is going to be called the request, which is going to be of type request. And here we have our response, which is going to be of type response like this. This is our function body.
Speaker 1
06:19:21
We're going to have some data that we're expecting from the front end. Here let's have const, we're going to get access to those data, which is going to be called to awaitRequest.json like this. We can already define the types for data. We're going to have a request data here.
Speaker 1
06:19:40
A request data is going to be this object. We have the check-in dates. Check-in date is going to be of type string. And we're also going to have the checkout dates, which is going to be of type string.
Speaker 1
06:19:55
And then we're going to have the adults, which is going to be of type number, children, which is also going to be of type number. We're going to have the number of days, which is also going to be of type number. And lastly, we need a hotel room slug. This is going to be of type string.
Speaker 1
06:20:29
String like this. So we have our request data, we are going to use it here and say this is going to be of type request data like this. And here we can get the check in date, we can also get the adults, check out the children, hotel rooms log, and also the number of days. So we're going to get all of these from the request.
Speaker 1
06:20:54
So from the request like this and we need to call this like this. Alright so up next we can have some validation So we can check if these properties are not there. Then we're going to return a new next response. And we're going to say, please, all fields are required.
Speaker 1
06:21:20
Like this. And then we can set a status of 400. So what are we going to check here we're gonna check if there's no check-in dates or there's no checkout dates there is no checkout dates, if there is no adults or hotel room slug or there is no number of days, then we are going to return this error. So we are meant to use or like this, not this.
Speaker 1
06:21:53
So if there's no this or no this or We don't have adults or there are no other rooms like this. And, you know, number of days. So if these properties are not set, then we are going to return this error. Now we're not checking for children because children can be 0 if the user don't pass.
Speaker 1
06:22:21
That's the default that we are using in our page. So here children is 0. Or is it? So number of children is 0.
Speaker 1
06:22:28
So if we check for children and we get 0 value, which we're actually allowing our database, they are going to have an error. So that's why I'm not checking for children here. Okay, so after this, we can go on and get to the request origin. So cost origin is going to be equal to request dot headers.
Speaker 1
06:22:48
And here we can get and we're going to get to the key of origin, like this, that is going to give us the request origin. And after that, let's have access to the session. So session is going to be called to awaits and then we await our get server session. And this needs the auth options.
Speaker 1
06:23:07
So we're going to pass our auth options here, coming from our leaps folder. So where is it? So our auth options. And Here we're going to have our session.
Speaker 1
06:23:21
We can have a check. If there is no session, then we are going to return a new next response like this, and We're going to say authentication required. Now, because of our middleware, So this middleware we have here, you know that only authenticated users will be able to visit this route. So this check is not needed.
Speaker 1
06:23:52
But I actually want to go in and get access to the user ID. Okay, so const user ID. And we're gonna get it from our session.user.id like this. So this gives us the user ID.
Speaker 1
06:24:08
And we can also format the checkout date, the date. So format that checkout date. And this is going to be called so our checkout dates. So not checking here, check out dates.
Speaker 1
06:24:24
And then we can split by t, this capital T, and get the first index. Now, if you're not sure these values, please just log these to the console and you'll see the format of the checkout date. And I'm just going to change this to formatted check-in dates. And then this is going to be our check-in date, the split.
Speaker 1
06:24:44
Alright, so here, after all of these, let's have our try catch block. And in our catch block, in case of any errors, let's first log to the console. So we're just going to have this payment failed and have the error. Okay, so let's return a new next response.
Speaker 1
06:25:09
And the body is gonna be empty and we can set the status of 500 like this or we can just send the error like this we have this error so this is going to be of type any and the error is gone now in our try block let's try to first of all get a room because we want to get all the details about the room from our Sanity Studio. The only thing we want to get is the number of days. Okay, so we need the hotel room slog to get the room and then the number of days. We're going to use this number of days to then calculate the price ourselves.
Speaker 1
06:25:45
Okay, and not allow the user send any data to the front end. So how do we go about it? We are first going to get our room in our try block. So here, we're gonna get a room.
Speaker 1
06:25:58
And this is going to be called to our get room. Remember the get room from our leaves. If we visit this get room, you see here that this gets a room so it's gets this query, this gets from query and it returns the results. Okay, so we are making use of this get room it needs a slug and we're gonna pass the hotel room slug so this hotel room slug okay so after getting the room let's get the discount price because you know we are giving discounts on some of the hotel rooms and this is going to be equal to the room dot price Minus the room dot price Divided by 100 And we're going to multiply this value by the room discount.
Speaker 1
06:26:49
So this is going to give us the discount price now. Okay, so after this, let's get the total price, the total price is going to be the discount price, which is the discount price per unit, we're going to multiply it by the number of days. So once we multiply the unit price by the number of days, we're going to get the total price. And now we are going to come over here and create a stripe payment.
Speaker 1
06:27:16
Okay, so we're sure we have all that we need now to create a stripe payment. So we're gonna have this stripe session. And this is going to be called to await stripe. That is this Stripe instance that we formed here.
Speaker 1
06:27:34
So this, so we're going to await Stripe and then we can call checkouts. And here we have sessions. And then we have the create method. And this is going to take a mode and the mode is payment.
Speaker 1
06:27:48
It also takes the line items and the line items is this array. Okay, so an array of objects. And first, we're going to pass the quantity, the quantity is 1. So the quantity is a mandatory field.
Speaker 1
06:28:04
And here let's have the price data. The price data is going to be this object, so we can specify the currency and the currency we support is USD. We are going to have the product data. The product data is this object where the name of the product is the hotel room name.
Speaker 1
06:28:21
So I think is the room dot name. Okay, and we need to provide images, and images, sorry, images like this images is an array so you know that our room images has the URL property so we're going to have our room and then have images we're going to map through each image like this and then this is going to give us each image and then we're going to return the image URL so map returns an array and automatically images is going to be an array alright so after the line items next we are going to send a payment method types. So on this copy maintenance committal is the types and we support card payments. And after this, we have this we need a success URL and the success URL is going to be dynamic.
Speaker 1
06:29:16
Remember, we have the origin, which is, or is it this origin over here. So we're going to go to our origin, and here slash users. And we want to go to the user ID. So user ID like this.
Speaker 1
06:29:32
Remember, this user ID is coming from our session here. OK, so now we have all of these. We still have all these fields to create a booking. We are not going to be creating a booking here, all right, because we want to only create a booking when this payment is successful.
Speaker 1
06:29:49
So that's why we are not calling this route. Stripe gives us access to webhooks, which is more like subscription events that we can subscribe to. And these events are going to be called for us automatically by Stripe when they occur. So we're going to be looking at the webhooks functionality next and how we can create an order only when the payment is successful.
Speaker 1
06:30:09
But for now, let's just test that our payment is working. Okay, so after this, we need to return the response. So we're going to return a next response.json. And here we have the Stripe session.
Speaker 1
06:30:25
And we are going to have this, so we set the status to 200, And then we can have a status text. Status text like this. And the status text is just going to be payment. Let's say payment session created.
Speaker 1
06:30:45
OK. So we can, for us to test this out, we need to wire up Stripe on our front end. So we just did the back end. Now we need to have Stripe in our front end.
Speaker 1
06:30:58
And let's come over to our leaps. So we're going to have a file here for stripe dot ts. And to continue, let's quit our development server. And we need to import the stripe for the front end so a stripe for slash stripe hyphen JS So we need to install this library.
Speaker 1
06:31:22
All right, so we're going to import some properties from it. So import all of these from at stripe, stripe JS like this. And let me restart, sorry. Let me restart development server.
Speaker 1
06:31:39
All right, so what are we gonna take? We're gonna take the Stripe class and then we're also going to take the loadStripe like this. And we're gonna have this variable, which we'll call stripePromise, which is gonna be of type promise. And this promise can resolve to 2 values so sorry it's hard to be here this promise can resolve to stripe or it can resolve to null like this.
Speaker 1
06:32:06
So here, we are going to have this function that is going to help us to get stripe. So we're going to export this const, which we call getStripe. And getStripe is going to be called to this function. And we are going to return this getStripe function.
Speaker 1
06:32:27
All right, so what we want to do here, first we want to check if there is no stripe promise. Then we are going to say our stripe promise is going to be equal to load stripe. So this package that we import like this, we're not going to return here, sorry, we already exported and we need to return inside. So we're going to return inside and not here.
Speaker 1
06:32:54
So we call those stripe and those stripe is going to need a publishable key so we don't have this yet so we can say this is going to come from our process.env.next underscore public underscore stripe publishable key stripe publish shibu key like this and we can say a string all right so I'm going to copy this and load it in our env and get it from our Stripe. So this is a publishable key. Just copy this and I'll paste this in here and save. So whenever we make changes to our ENV, it's always nice to restart our server.
Speaker 1
06:33:44
So I'm gonna quit this and restart our development server. Okay so now we are done with this we would come back to our page so this room details page and in here we have this function so to handle book now click this handle book now click function okay so what we can do here we have the number of days here, where we are going to be integrating stripe, going to take this off. And we have our try catch block. So first, we're going to use xs to send data.
Speaker 1
06:34:19
So this is going to be a code, so we're going to await exeos.get. And we need to import Exeos from Exeos, like this. And here, we are going to call xeos.get. And the API is going to be slash API slash stripe.
Speaker 1
06:34:42
So this endpoint, if you open this up, sorry, not this. If we come to our API stripe this so this route over here and it has to be a get request sorry post request not get so this has to be post like this alright so after this because the post request we need to pass data and what data we need to pass a check in dates, we also need to pass the checkout date. We also need to pass adults, we need to pass children. And children is going to be a number of children like this, we need to pass the number of days and we need to pass the hotel rooms log like this.
Speaker 1
06:35:32
Having this error because we need to make this async. Alright, so from this, we are going to get our data. And we can name this we name this to be stripe session. OK.
Speaker 1
06:35:48
So after this, we're going to check if we have stripe. That means we need to import our load stripe function like this. And somewhere here, we can just say const stripe is going to be called to await getStripe. And this is this getStripe here.
Speaker 1
06:36:13
So we're going to import this to help us load stripe here. And let's see. So this is it. OK, so once we await this guest stripe, we now have stripe like this.
Speaker 1
06:36:26
And why are we having an error? Why do we have this error? OK. Can have const results.
Speaker 1
06:36:38
We have an error here, which is saying an expression of type void cannot be tested for tracefulness. It's a TypeScript issue. And if we come back here to this get stripe function, that's because here, we forgot to return. I forgot to return our stripe promise.
Speaker 1
06:36:57
And that's why I love TypeScript because it helps us to catch errors like this. So if I go to return a stripe promise, and that's why we're having error here. I see the error is gone because it knows it's gonna return stripe or not. So const result is going to be equal to we await stripe.
Speaker 1
06:37:19
We await stripe like this And then we call redirect to checkout. Redirect to checkout here. And this is going to take the session ID. And the session ID is going to be what we get back as data.
Speaker 1
06:37:37
So stripe session dot ID. OK. And this stripe session we're getting back here, it will come to our route. See here, we are sending this back as a response.
Speaker 1
06:37:53
So this Stripe session, and then it has the ID property. All right, so here we have our results. We can have to check. So if inside here, so if results.error, we're just going to have a toast.
Speaker 1
06:38:11
So we're going to toast.error and say, payment failed. And here, if we have an error, let's log it to the console. So we can console.log error. And here we have our error like this.
Speaker 1
06:38:35
And then we can also toast.error and say an error or code. Yeah. All right, so this is the time that we're going to test it out. This is our page.
Speaker 1
06:38:55
And we are calling this post request, we pass the data. So checking dates, checkout date, adults, children, number of days, which are all these data. Check in date, check out date, adults, children, number of days. And here, even though we're not making use of these properties yet, because we're not creating a booking, we are just creating a payment.
Speaker 1
06:39:19
And here we're not making use of the total price. And that's because just here, so in our price data, so after product data, we are going to add a unit amount. So we forgot to add the unit amount. So the unit amounts are going to pass in like this.
Speaker 1
06:39:43
And we're going to have our total price and multiply by 100 because it has to be in cents and we can call to string like this and like this. Alright so let's try this out I will save open the terminal to be sure everything is still up and running I'll just quit and reload so that we had just double, double show. I'll close this panel. And if we come back to the browser, here where we have our application, let's just reload.
Speaker 1
06:40:16
So let's see if our application is building. So it's compiling the slug. So that's page. And remember, we have middleware in place.
Speaker 1
06:40:24
So if a user is not authenticated, or even not authenticated, maybe you're clicking on the book now button, and nothing is working, you just have to authenticate yourself so if you're not authenticated you'll not be able to visit the api route we don't have a way to manually log in log out yet so you know once we implement logout functionality you would see how this works so our page is compiling And I think it is ready now. Alright, so this is our page. Let's choose a check-in date. I'm going to choose 12 and a checkout date.
Speaker 1
06:41:13
I'll just choose the next day. You see the price is 92 because of the 8% discount and let's click on book now. So let's see if this goes on to load Stripe. Okay.
Speaker 1
06:41:30
Okay seems it's loading up Stripe. So great. Everything is working fine for now. We have 92 we have the product image You can give this a name or email.
Speaker 1
06:41:40
I'll just go with test at test.com for card information 42424242 is the default that Stripe gives us and for the month I'll just say 11 23 on any CVV I'll just say test name and click on pay So wait for this to load up, it's successful. And it should redirect us to the user, so a 404 page. And you know, we created this page here. So if you come over to the routes here, you have the success URL.
Speaker 1
06:42:15
So it's origin, which is for now our localhost slash users and the user ID. And that's how we get redirected to this page. So for now, it's a 404 page, but we'll be fixing that. So if we come back to our localhost, And let's also come to our Stripe.
Speaker 1
06:42:34
And here, if we click on payments, so that we see our payments, we should see this payment. So this is it. So we just did this payment now and payment is complete. So a user is successfully booking a hotel room.
Speaker 1
06:42:48
So fine. Now we need to create a booking. So a user is paying, but you know, we are not actually creating a booking. And that's where webhooks come into play.
Speaker 1
06:43:00
So if we come back to home and here in home, where is it? You come over to webhooks. Here you would see how webhooks work. So you can click on this link.
Speaker 1
06:43:15
I'll just open this in a new tab. And over here, you're going to see an API documentation on how to go about using webhooks. So let's scroll down and let's visit this is going to give us a way to go about this. And in here, you see the first thing we need to do is to identify the events to monitor.
Speaker 1
06:43:36
I already identified the event that we are going to monitor for this webhook and the webhook is the checkout session completed. So the checkout session completed is the webhook that I have identified or that we need to call whenever a checkout session is completed. Okay so we need to identify the Stripe event so you can open this event in a new tab to see a list of the different events that Stripe offers. Okay and here I'm going to search for Stripe, sorry for checkouts.session.completed Like this and this is it.
Speaker 1
06:44:18
So this event here, where is it? Where is it that's completed I thought it's because the let's see So check out dot session dot completed Okay, check out the session. Yeah, so this this web book here So checkout.session.completed. Okay, checkout.session.
Speaker 1
06:44:40
Yeah, so this webhook here, it occurs when a checkout session has been completed. So this is the event we are going to be listening to like that. Now we need to create a webhook endpoint function. This webhook endpoint function, Stripe is going to call for us.
Speaker 1
06:44:59
Let's do this next and come back to see the next implementation. This gives us a sample code. If we go back to the Node.js, you see how it works in Node.js, so this slash webhook and all these things. Let's create this webhook endpoint function.
Speaker 1
06:45:19
And to create this here, so in our API route, I'm going to create a new route. And this route, I'm going to call webhook like this. And here, we are going to have, sorry, where is it? We are going to have the route.
Speaker 1
06:45:39
Yes, fine. Just inside the webhook. Okay, so how is this going to work? Let's first of all have our checkout session completed.
Speaker 1
06:45:49
So checkout underscore session underscore completed. And this is going to be equal to checkout underscore checkout.session.completed. We just saw this in the documentation. This is the event we are going to be listening to, the checkout.session.completed event.
Speaker 1
06:46:14
We're going to get Stripe again. I'll just come back here and copy this so here we are going to get stripe again and we need to import stripe from stripe like this so after this list we can now go on to export our async function. Async function. And this is gonna be a post request.
Speaker 1
06:46:44
Like this. And this post request is going to be called with the request which is of type request. And here we have the response which is going to be of type response like this. And in here, first we're going to get access to the request body.
Speaker 1
06:47:09
So const request body. And request body is going to be called to await, like this, request.text. And next, we need to get the signature and this is going to be equal to request.headers.get and we're going to get the stripe signature. Okay, so where am I seeing all of these from the documentation?
Speaker 1
06:47:41
And if you scroll down, you will see best practices. Where is it? I think that's the last step. So after number 4, let's see.
Speaker 1
06:47:54
Somewhere here we should have 4 best practices. Let's see. Test your webhook function, register and secure your webhook. Okay, so here we have best practices.
Speaker 1
06:48:10
And you have, let's see, secure webhooks. Yeah, so the webhooks best practices, you can upload this link. And here you're going to see best practices to integrate Stripe inside of your project. And here you see only listen to event types your integration requires.
Speaker 1
06:48:30
That is 1 best practice. And here you see you need to verify events that are sent from Stripe. And here you see ways to go about it having the signature getting from the request headers and here having the Stripe webhooks construct event you pass the request body, you pass the signature, and you pass the endpoint secret. Okay, so we are going to be doing all of these, which is just best practices for us to secure event listeners.
Speaker 1
06:49:01
Okay, so for now, we are still in the second step to create a webhook endpoint function. Alright, so after the signature, we are going to have a webhook secret, which we don't have yet. Okay, so we're going to get this when we integrate the webhook. But for now, this is going to come from process dot env.
Speaker 1
06:49:30
And here we can call it stripe underscore webhook underscore secret, like this. And I'm going to copy this and have it in our env for now, which is going to be empty. And after getting our webhook secret, we're going to have our event, and this event is going to be of type stripe.event, like this. And after this, we can have our try catch block.
Speaker 1
06:50:02
So in the catch block in case of any error let's copy this and use here. So the next response needs to be imported from next server. And the error, we can just say web hook error like this. And this is going to make use of back tick.
Speaker 1
06:50:30
And we are going to have error.message, like this. And this is going to be of type any. So in our tribe lock, let's get that verify. So it is no signature or there is no webhook secret, then do gone and return.
Speaker 1
06:50:54
So if we have all these properties, we are going to assign our event to be equal to stripe.webhook like this. And here we have the construct event. And this is going to take the request body. And this also needs the signature.
Speaker 1
06:51:14
And it needs the webhook secret. So you see here, need a secret. And we'll pass the webhook secret here. All right, so we have this.
Speaker 1
06:51:26
We can come over next, after this try catch. And this is where we load our events. Load our events. Okay so in here we're going to have a switch case And we're going to switch by the event.type, like this.
Speaker 1
06:51:51
And we're going to handle this case. So this is our case, checkout session completed, like this. And we're going to have our cost session. And this session is going to be the event data.
Speaker 1
06:52:07
So event dot data dot object, like this. Alright, so for now, we're just going to console dot log the session here. So we're just going to log this session to the console. We can already have a default case.
Speaker 1
06:52:30
We can already have a default. And will just console.log unhandled event type. And here, we're going to send that event.type like this. OK, so What do we do next?
Speaker 1
06:52:52
We log the session to the console, and after which we can go on to create a booking like this. We go on to create a booking, And we need to return a response. So we're going to return a next response, the JSON. And this response is just going to say booking successful.
Speaker 1
06:53:17
And we set a status of 200 and a status text of booking successful. So this return is under this case. Okay. And this should be it.
Speaker 1
06:53:37
So we are going to try this session type and let's come back to the documentation. We have created a webhook endpoint. So we have done this and you see here you have this switch and you have this case which is what we did we handle this case for when our session is completed and you see here there's this default that we just log to the console and this response okay so I think we haven't forgotten this So we need to return a response to acknowledge the receipts. We're doing that.
Speaker 1
06:54:15
We are not doing that. Okay, so this needs to be copied and returned outside of this switch here. We need to make sure we return this. Okay, regardless.
Speaker 1
06:54:30
And we need to return this, why this whatever code we write inside here, whatever logic is being worked on. Okay, we need to return this, which is what we have done and everything here is fine, We can change the status text rather than booking successful, which isn't what happened. You can just send event received like this. Okay, so let's come back and after this we need to test our webhook function.
Speaker 1
06:55:03
And how do we test this? We need to use the CLI. So I'll just open this in a new tab and come over here. So here we need to first of all install.
Speaker 1
06:55:16
So I'm on a Mac and I installed with Brewer. You see you have different options for Windows you know this is the way you would go about it you just need to download the file and you know follow this to download the Stripe CLI so you can test this locally on Linux. If you're on Mac you can you know have different ways to go about it but I just use homebrew to install. I advise if you're on Mac you should try this out it's just very much straightforward and when you install you need to log into your Stripe dashboard and we should be doing this already.
Speaker 1
06:55:51
So we're going to go to our dashboard, our terminal, sorry, and run this Stripe login and Where is it? Okay. So this is it. Okay, so this is just all we need to do.
Speaker 1
06:56:11
We need to login. So I'm going to open up my terminal. And I will zoom in quite a bit. So I'll paste this Stripe login and this should be after you have installed the Stripe CLI.
Speaker 1
06:56:24
Alright, the parent, please enter the browser of this. Okay, so I'm going to enter to open the browser and this opens up in the browser here and in here we should be authenticated. Let's just wait for this to load. Okay, so we need to verify So let's come back to the IDE, this snappy valor, you know, text, and we need to verify.
Speaker 1
06:56:57
So this is it. So this is a pairing code. So snappy valor. And here you just allow access like this.
Speaker 1
06:57:04
And, you know, okay, so once you authenticate, I'm going to clear this. And after that, we need to listen to events to local endpoints. So I'm going to copy this stripe, listing and forward to here. And we are going to add this dash, dash skip verify flag here like this.
Speaker 1
06:57:30
So inside here, I'm going to paste this. We need to change the first, let me add a dash dash skip verify flag. Let me be sure, skip hyphen verify as 1 word like this. The endpoint is going to be localhost 3000, slash API slash webhooks like this.
Speaker 1
06:58:02
This is our endpoints and I'm going to enter this. This is going to load and we have our Stripe secret. So you can copy your Stripe secret and come in your ENV and paste this secret here and save. Okay since we have changes in our ENV we are going to restart our server like this and you see if we come to this webhook section so this route we take the request body we take the signature from the header, we have our webhooks secret, and we have our event.
Speaker 1
06:58:44
And if there is no web signature or webhooks secret, we return, we assign an event. And here we switch the event type. And we just log to the console. And here we send this response of events received.
Speaker 1
06:59:05
So I'm going to change this to events received like this. And for now here, we are just logging this to the console. So open up the console in case we see any logs and come back to the browser. And next, we are going to trigger the webhook.
Speaker 1
06:59:29
So If we come down, you see here to forward events from the endpoint, you're already registered on Stripe. Use the load from webhooks API optional flag. So if we come here, you see this is the webhook that we have registered and striped. So this webhook over here, this endpoint.
Speaker 1
06:59:58
And you see it's listening.
Omnivision Solutions Ltd