All right, guys.
So in the last video, we went over some small fixes, some small bugs.
In this video, I want to address two pretty large bugs.
And you have to realize that when you create a project for a course, it's not like a production project
where it was a business and you're actually using it to make money and so on, because that takes a
lot longer.
You have more people working on it, so you can expect to have bugs in course projects.
But I want to be fully transparent and this is a pretty big one, so I want to address it and show you
guys how to fix it.
So basically, if someone is tech savvy enough the way we have the project now, they could actually
make a request to this order slash pay.
If they knew the correct info to add, they would have to be logged in, so their token would be traced.
But regardless, they, they could be they could be able to get stuff for free.
They could basically just bypass the part where it sets the is paid to true and do it themselves, which
obviously isn't something you want.
So what we're going to do is instead of just marking it after the transaction goes through and then
marking it is paid.
True, we're going to make a separate API call to PayPal to verify that the transaction went through
when it was actually paid for and it was completed.
Okay.
Then we get an access token back and then we can check it with that.
The second issue is the price calculations.
Right now we're calculating the prices for the items, the tax, the shipping.
We're doing it all client side where again, if someone was tech savvy enough, they could actually
change those values to zero and again, get free stuff sent to them.
So we don't want that either.
So what we're going to do is do the calculation on the server side.
So those are the two big bugs that I want to fix.
Now the first thing we're going to do is just add these PayPal environment variables because to make
that API call, we need these.
We need our app secret.
We also need this API URL, which if you go live and you don't want to test anymore, you would just
get rid of sandbox and it would just be m dot paypal.com.
But let's go ahead and grab those.
And by the way, this document, it's in the premium docs at Travis Media.com, but I will include it
on all platforms within the course files as well so that you have it and you can just because I'm mostly
going to copy and paste this stuff now, I don't want to show my dot env file.
So what I'm going to do is just I'm going to copy this and I'm going to put my secret in the variable
and to get the secret you can just go to your PayPal credentials, apps and credentials and just make
sure you copy this.
One is for the Secret.
This one here is for the client ID, So just grab that and paste it in.
I'm just going to do that off camera real quick.
All right.
So I did that.
You're going to want to just restart the server if you're in development, because when you add a new
environment variable, the server has to be restarted for it to take effect.
So now let's go back to.
Let's see.
Let's go back to that, the document there.
And next thing we want to do is make our call to PayPal.
So this code right here is going to go in a file called PayPal JS in our utils folder.
So what I'll do is copy this, create the file, and then I'll just go over it real quick and you can
find this stuff in the PayPal documentation as well.
So we're going to create in back end utils a file called PayPal dot JS and then we're going to paste
that in.
And a lot of this is commenting.
You can see we have three functions and before each function we just have a header telling, telling
us what each parameter is, what it returns and etcetera.
So we bring in dot env because we are using our client ID app secret and API URL.
Now the three functions we have are get PayPal access token.
We have check if new transaction and we have verify PayPal payment.
So the get access token is a helper that's going to be called within this function.
But this is what's going to verify that the product was actually paid for before we mark it as is paid.
So we get the access token with the get PayPal access token function, which is up here.
So basically we create a base 64 hash that includes our PayPal client ID and the PayPal secret.
And then what we do is we're going to make a request to this URL.
So PayPal API, URL, v one, OAuth two token, and in the headers we're going to send authorization
and we're going to send basic.
And then that auth, that hash that we create here.
Okay.
So that will validate the PayPal client ID secret.
And then in the body we just need to add this grant type and set that to client credentials and then
we make our request.
So we're just using fetch here, make a post request, sending the headers in the body, and then if
the response is not okay, we're going to throw an error that says failed to get token.
And if it passes, then we're going to get the data from response dot Json and we're going to return
the access token so that gets returned down here.
That will get put in this variable, then we're going to make a request to check out slash orders slash,
and then the transaction ID because this will take in the transaction ID, And then for the authorization,
we add our access token, our bearer token.
And if that isn't okay, it's going to throw an error.
And then if it is, we're going to get the PayPal data and then we return this verified.
So if it's completed, then verified will be true.
And then we also have the value.
All right.
So we're going to be calling that function.
We're also going to be calling this function check if new transaction.
And what this is going to do is go through the orders in our database and look for that transaction
ID.
If it's there, then we know it's not a new transaction.
So it'll return false here.
If there's none, if the length is zero, then that means it's a new transaction and we can proceed.
So that will return.
True.
All right.
Now we're not calling any of these functions yet.
We're just we're just creating them.
So make sure you save that file.
We can close that up.
And now let's go back to the document.
And this just kind of explains what I just told you, the three different functions.
Now, to calculate the prices on the server, we're going to have a new file in utils called calc prices.
And this is essentially the same thing that we did on the client.
But again, we don't really want to do this on the client because if someone is tech savvy enough,
they can change the values and set prices to whatever they want, set tax to whatever they want.
So let's copy that.
And then in utils, let's create a file called Calc Prices Dot JS, paste that in and basically we're
returning the items price.
So all the items combined together, whatever's in the cart shipping tax and total.
Uh, let's see.
What is this error here?
Did I?
Oh, yeah, I missed that last.
Curly brace.
Okay, so we have calc prices, so we have all of our functions created.
Now we need to implement them.
So let's come down here to use our new functions and where we're going to use them is going to be in
the order controller because that's where all the order stuff happens.
So we're going to bring in our product model because we will need that and then we're going to bring
in calc prices as well as verify PayPal payment and check if new transaction.
So the functions we just created.
So let's go into back end controllers order controller and let's paste that in.
Now, the two functions we're going to be changing are add order items.
And of course, the update order to paid, which right now doesn't do any checks with PayPal.
It just waits for the order to be created, the PayPal to be paid, but not checking it, not verifying
it and then marking it.
True.
Which we don't want.
So let's go back to the document.
And let's see.
So this is going to be the new add order items.
So what I'll do is just grab this.
Again, This document will be in in the course files.
And let's go ahead and paste that in.
So what we're doing different here is now we're not getting the price, the calculated prices from the
body, from the client.
So we took those out and then we're checking if the order items are there and the length is equal to
zero.
If it if that's true, then we're going to send a 400 because there's no order items else.
Then we're going to get the ordered items from the database and we're going to map over the order items
and use the price from our items in the database.
Okay.
So we're not getting them from the client.
We're getting it directly from the database and returning that.
And then down here, we're going to calculate our prices by calling our calc prices function and passing
in the order items, and then we're just destructuring to get those prices.
Then we're going to create the order just like we did before, except now our prices are safe and then
we're setting order items as the user to the logged in user shipping address, payment method, all
that stuff, and then it's going to create the order.
All right, So that's that.
Now for the update to paid.
So let's and this is again, this is just explaining what I just said.
So update order to page function.
We're going to grab that.
And let's go down.
To write here, update or to paid.
And we're going to replace what we have here.
So what this is doing is we're going to call our verify PayPal payment, which makes that separate request
to the PayPal API, gets the token, verifies the payment, and if so, then this verified will be true.
All right.
So if it's not true, we're going to pay and we're going to send an error.
Throw an error that says payment not verified.
In addition to that, we want to check to make sure that it's a new transaction.
So we're also calling that check if new transaction function that we created in the PayPal JS file,
then we find the order.
If order then paid correct amount, we're going to set that to the order total price, set that to if
that's equal to that value.
If that's false, then we know it's the incorrect amount.
Okay.
So we're checking those prices and only if then if all that stuff is true, then we set is paid to true.
Okay.
We also set the paid at to the date and then our payment result.
So this is stuff we've already been setting, so there's nothing else we have to do here.
We just save the order, All right.
And return the order.
So that should be it for.
For this file, the order controller.
Now, I'm going to go back to the the documentation here that just explains what I just showed you.
Now, in the order screen, we're just going to add this dot unwrap because we're having some issues
with with how errors were reported.
So that's actually in the front end.
So front end screens and then order screen.
And we want to put that.
Uh, let's see.
So that's going to go on the pay order function.
So let's see.
Where do we use that?
Right here.
So wait, pay order and we're just going to add dot unwrap.
So now we're going to go to our project and I'm going to add something to my cart and we're going to
proceed to checkout.
Place.
Order!
Okay.
The order is placed, but it's not paid yet.
Now, what will happen when I click this PayPal button is it's going to send that API call out that
we just created.
It's going to get the token, it's going to verify everything and we should be good.
So let's click on that.
Use my dummy account here.
Complete purchase.
And there we go.
Order is paid and you can see right here, paid on and then the date.
All right, so the final code with the bug fixes are in the GitHub repo.
So if you need, you can use that.
You should also have the documents that I created in the course files.
But that's it, guys.
I just wanted to be transparent and if I make a mistake, I want to address it.
And it also gives you guys a little bit of more of a learning experience because you have to go in and
refactor and stuff.
So.
But that's it.
Guys, thanks for watching and I will see you next time.