So let's now start working on integrating
this payments feature.
Conveniently, we got this code snippet here,
which tells us how we can start making charges.
And here, I got the Node example,
which already assumes that we use Express,
which is even more convenient.
Now, what we will have to do as a first step is in our code,
we have to identify a place
where this code should be added in the end.
And the place to do that should of course,
being the orders.controller, where we add an order.
This is the controller action we execute
when a user clicks on that Buy button in the cart.
So that is where a user wants to be charged
because he or she decided that he or she
wants to buy the product.
So therefore, in addOrder,
I still wanna store the order in my own database,
because we might still want to have that data there.
We might still want to be able to administrated
through that administration interface we built.
But in addition,
I also want to charge the user with help of Stripe.
Therefore, what I'll do
is after storing my order and clearing my cart,
I wanna make that real charge.
Now, in reality,
we therefore also might then wanna check
if that charge succeeded and roll back our changes
if it fails,
but here I will just assume that it does succeed.
So hence, after req.session.cart,
I wanna make that Stripe payment.
For this, we first of all, need to include
this Stripe package which we added to our project
into this code file.
And we can copy this line for this.
And this line can be added at the top of orders.controller.
Now, here we required a Stripe package
and then we also do something else.
We in the end execute the function
that seems to be provided by this package.
The Stripe package seems to export a function
as its main thing, and therefore, we execute this function
by adding parentheses here.
Alternatively, if this is confusing,
we could do this in a two-step process
and have our stripeObj, let's say, by executing stripe,
which I import here as a function.
So both is possible.
The important thing is that we execute the thing
that's provided by the Stripe package as a function.
So I'll go back to the original approach.
Now, to this function, a string has provided as a value
and that string includes some random looking
combination of characters.
This is a Stripe key and in the Stripe documentation,
if you would be logged in
whilst being on the documentation page,
which I'm not in this case here,
you should actually see your concrete key here
in the documentation.
Either way, you can always go to your profile,
your account profile and there to Developers, API Keys.
And here it's this secret key which we need.
You should reveal that test key, that secret key,
copy that key.
And it's called secret key because you shouldn't share it
with anyone else.
I will reset it, I will delete it
after recording this video,
so you can't use my key.
You should never share it with anyone else
because this key can be used to make charges
connected to your account.
And it's this key, which you pass here between the quotes
as a value as a string to this stripe function
that we execute here.
This will then be used internally by the Stripe package
for sending requests to Stripe.
Now, the next step, as we see here,
is then to create such a checkout.session
in the place where we wanna make that payment.
So therefore, I'll copy this here, this code here.
And at that here after req.session.cart.
Here at the end, we also redirect,
and therefore, I will not redirect myself anymore.
I'll come back to what we do here in a second.
So let's see the value of the code we just copied.
What does this do here?
We use await here.
So of course, our function
should be async function for that, and it is.
And then we use this stripe object,
which we got from the Stripe packaged
by executing this function.
This then yields our object.
And we use this object,
and then we access the checkout property
on that stripe object.
Now, we know that we can access this
because we find this code in the official documentation.
And here, we are already tapping into Stripe's API.
We're not sending a request to Stripe yet,
but we're tapping into the API of the Stripe package.
So we're using the interface of that package,
we are using a clearly defined action or in this case,
a clearly defined property to do something
with that package.
And we find out which properties and methods we can use
by looking at the official docs.
So we use the checkout property.
And then on that, it seems to return an object as well.
We access the sessions property,
and that also seems to return an object
with a create method.
The session here by the way,
has nothing to do with our own session
that we created before.
A session instead as a more general term
that is used for our ongoing,
well yes, session of ongoing process you could say,
that you established with some server.
Here, we are about to establish an ongoing process
or session with these Stripe's servers you could say.
And we do establish that by calling create.
Now, create takes an object, hence the curly braces,
with various keys that configure this session.
And these key names here are not up to you,
instead these are key names Stripe is waiting for.
So these are clearly defined key names,
and hence, it's all part of Stripe's API.
For example, we have to define the payment method types
that we wanna handle.
And here, we'll focus on credit card payments.
Again, we see this here.
The value here is also not up to you,
you have to use one of the supported value types
and card is one of them.
You find others here by cycling through the different
payment types of Stripe supports.
And you see how the code changes on the right
if you do that.
And then you define the items that should be purchased.
Now here, we have to set the price that we wanna charge.
And now here we have to be careful.
The price field in this object,
which we add here to line items,
actually has to be an ID as it says here.
And it has to be an ID pointing at a price object
defined on Stripe's servers.
If we have a look at our account,
we see that we can configure a lot of things there.
And it turns out that you can actually store your product,
not just in your own database,
but you could also use Stripe
to manage your products and prices.
And if you stored prices for your products
on Stripe's servers, which we haven't done here,
you could point at a specific PRICE_ID to let Stripe know
which price it should fetch from its own database.
Now, here, in our case,
we haven't stored any pricing data on Stripe's servers.
And therefore, we'll choose plan B here.
In new official docs,
we see that we can work with the predefined PRICE_IDs,
or we create price_data on the fly
with that price_data thing here, on which I clicked.
And then we learned that in the line items,
we can optionally to price also add price_data,
and that's what all do here, price_data.
This then has to be an object
where we describe the price
just in time for this specific transaction
without any data being stored on Stripe's servers.
For price_data, we have to define a currency,
it's required as you see here in the documentation.
And it has to be a three-letter standardized code
in lower case.
So in my case here, I'll add currency: usd, like this.
And then in addition, we need either a product
pointing at a product stored on Stripe's servers,
which we don't have, or relevant for our case,
product_data, which again is just defined in time.
So here, I'll then add product_data
just as I added price_data.
And that's another object with more details
about the product that was ordered.
And here we then need to define at least a name
and we can also send more data if we want to.
So here I'll focused on the name, and say Dummy right now,
because we will populate that with real data
a little bit later.
Now we also need to go back to price_data,
and there, we also need to provide the amount
that we wanna charge
as a decimal number or as a non-negative integer in cents
Using this approach where you provide the amount in cents
instead of as a decimal number, can avoid rounding issues
where if a user adds 15 items to a cart,
15 times the same item with a price that ends with .99,
you could run into some rounding errors
because of how JavaScript works.
That's why you might wanna prefer a price
sent as a integer number in cents.
Now, for us, it sounds like maybe unit amount decimal
is more fitting since we work with prices
that are expressed as decimal numbers.
We do have decimal places in our prices.
And therefore, we'll start using that
and see whether it works.
It actually won't work,
but I'll still start with that because I wanna show you
why it won't work before we then fix it later.
Unit amount is the one we need,
but we'll have to transform our prices for that.
And therefore, we'll start with unit amount decimal instead.
And hence, in price_data after the product_data,
I add unit amount decimal, and this will then be the price,
which we of course also have to populate with real data
in a couple of seconds.
But that's how we generally configured the items
that should be sent to Stripe,
so that a payment is made for these items.
Now, the mode should be payment.
And success and cancel URLs will be important now.
Because the Stripe API actually works such
that the user is redirected to Stripe's own sites
so that the charge can be made there
and Stripe will then redirect the user back to your site
once status finished.
That's why we have these success and cancel redirect URLs.
And that's why we redirect the user like this down here
after we configure this Stripe session.
We redirect the user to Stripe's website here,
so that on that website,
the payment can be made in a secure environment
and we don't have to worry about any details of that.
And then once the payment completed,
Stripe will redirect user back to our site
and they're either to success.html or cancel.html.
And here, I'll redirect to localhost:3000/success,
and localhost:3000/cancel.html.
Or not cancel and success.html, just success and cancel.
And now we will have to define these two routes
and the views for these routes
before we then in the next step,
of course, also populate the payment data
with the real data.
So let's quickly add the success and cancel views
so that Stripe will be able to redirect to us.
And for this, I'll go to views, customer,
because this clearly affects the customer.
And there orders sounds like a good place.
And there, I'll add a success.ejs file
and error or failure.ejs file.
And I'll grab the code from all-orders.ejs
and paste it in there.
Remove the orders.css import though,
and replace the title.
And then here, I'll keep it very simple.
I'll remove that list here, I'll just say Order failed,
Please contact the shop owner for more details,
something like this.
And then I'll copy it again into success.ejs
where I say success in a title,
and then say Order was successful here in the h1 tag.
And here, I'll say You can visit, /orders,
the orders page for more details, something like this.
These are my two templates.
Now we need routes for these templates.
And for that, I'll go to the order,
that orders.routes.js file.
And here, I wanna handle requests to get /success
and to get /failure.
And we now need to add the appropriate controller actions
in the orders.controller.
So there maybe at the bottom,
I'll add a very simple function getSuccess
where I just get the request and response object.
And where in the response,
we just render customer/orders/success.
In this case, we don't need to pass any data to that
so that's all we need.
And then I also copy that to have my getFailure function,
where I render customer/orders/failure.
Now these two new functions need to be exposed of course,
so that we can use them in our files
as we did it before in the course.
And then we can go back to the orders.routes.js file.
And here, for the success route,
I'll point at ordersController.getSuccess, like this.
And for failure, I'll point at ordersController.getFailure.
Now, if we go back to the orders.controller,
and there to our Stripe payment,
of course, I wanna tweak those success and cancel URLs
since I just set up routes in the orders.routes file.
These routes here, these URLs
should of course be localhost:3000.
So our domain /orders/success,
and here it should be /orders/failure
because that's the route I set up.
And with that Stripe should redirect to these pages
once an order was made.
Now, of course we have to ensure
that we're sending correct data to Stripe.