So we are getting closer to finishing this.
Now we want to populate line items with correct data.
And for this, of course, we want to use
the data from our cart. Now this of course means
that we need that cart data, and thankfully we do have it
stored here in this cart constant. We created this at the
beginning of add order and it comes directly
from res locals. So this is our cart, which we then also
use for storing the data in our own database.
And I cleared the session cart here. But the constant,
where I stored the cart before, still exists as long as
this function execution hasn't finished.
And therefore we can use this cart constant down there
to populate the line items.
Now for that, let's understand that here we need an array,
an array of objects that look like this.
Now cart actually has an items property,
which contains an array. But the cart items have the
wrong format. Now, what we can do here is we can set
line items equal to cart.items.map as we did it before
in this course, because you learnt that map is a function
you can execute on an array. It's a built in function,
part of the JavaScript API, so to say. That allows you to
transform all the items in an array to new items.
And this allows us to transform the cart items
to items that have this structure.
For this we pass a function tube map,
a function that will be executed for us.
A function that gets to concrete item automatically
as a parameter value.
And then for every function execution, for every item and
cart items, we return such an object here.
And we can now remove these square brackets.
And now we just have to populate the data here correctly.
For example, name and product data should now be
item.product.title. So the item we get here,
an item from cart.items, they are the product data and then
the title. Now for the price we need the price of a single
product, because we specified a quantity separately.
And therefore here I'll send item.product.price
And I'll add a plus in front of it to be super safe,
that we're really sending a number. And for quantity
I'll send item.quantity
That is how we store the quantity for a single item in
our cart. And we do this for all the cart items.
And therefore we send all the cart item data to
Stripe here to create this session.
We then redirect to Stripes pages, where this session
will be waiting for our customers so to say,
this session we created here.
Then the customer will be able to make the payment,
and then we'll be redirected back here.
That is the idea.
Now with that, lets see whether this works.
If we start our server again, and I'm back in the Shop.
I'm going to add this keyboard and then
twice the Magic Trackpad.
And then I'm going to log in with my user here.
Like this.
And now here if I click Buy Products, this fails.
And it actually crashes because Stripe
is complaining about my URL. It's not a valid URL.
And if we dig through the error message,
we find out that Stripe is talking about the success URL.
So it doesn't like my success and cancel URLs in the end.
And actually what it's complaining about here is that this
should start with http://
http:// and then Stripe considers this
to be a valid URL. So with this change made,
if I go back and I click Buy Product again,
it crashes again. But I'm showing this on purpose
because these are all errors you can absolutely run into,
and you should know how to debug and fix them.
Now we see, that again, thankfully Stripe gives us a helpful
error message. And it tells us that Checkout, the service
we are offering here. This service offered by Stripe
does not currently support usd prices with more than
2 decimal places.
Now this is an expected crash here, because I mentioned
earlier that we had a problem with the unit_amount_decimal.
If we have a look at the error sent by Stripe,
thankfully it contains a very helpful error message.
We see that currently Checkout,
this service provided by Stripe, does not support
usd prices with more than 2 decimal places.
And we passed in 59.99 here.
Now this has only two decimal places, right?
Yeah. But Stripe converts it to this. Because actually what
unit_amount_decimal does is it takes the price you pass in
and translates this into a pure decimal price,
smaller than $1. So this is the unit you could use if you
have super small prices, which you want to charge,
which are smaller than $1.
What we actually need here is unit_amount like this.
Which however does not want a decimal number,
but instead an integer number, where the price is
expressed in cents.
That's simply how Stripe works.
Of course we can easily convert our price to cents though,
by multiplying it with 100.
We can also call toFixed(2) first
to ensure that we only have two decimal places at most.
Then we convert this to a number, thanks to the plus.
And then we multiply this with 100
to get the price as an integer number,
so the price in cents.
And that is what we send with unit_amount then.
And that is what Stripe needs here
to process the price correctly.
With that if you go back and click
Buy Products again, now this works.
And now we are redirected to a page provided by Stripe.
If you check the URL, we are now on Stripe's website,
not on our own website anymore.
Now here we have to enter our credit card data.
And this interface and the validation of all the data,
that's now all provided by Stripe,
which is of course pretty convenient.
Here we also see the details about our products.
And now here we can enter some dummy data,
since we are in test mode.
In real mode you would have to enter real data, of course.
But for testing, we can enter testing data,
and no real transaction will be made.
Now for this, we can check out the official docs.
There if we scroll down, we find some testing data
that we can use,
and I'll use this default credit card number here
for a successful charge.
Again, this is just testing data.
But I'll use this credit card number here.
Enter some email address here. This doesn't matter.
No email will be sent.
Enter any expiration date in the future, and any CVC code,
any name, any country, and then click pay.
And now Stripe will process this data,
this testing data here. And you'll see,
we are redirected back to our success page.
Now as the owner of this Shop, who also owns this
Stripe account, which is connected to our code here.
As this owner, we can now go to our dashboard,
our Stripe dashboard. And under Payments,
if we have a look at that, we should see that payment
that was made a couple of seconds ago here.
I got a couple of older payments here as well,
which don't matter to us here.
These are from other projects. But here is the charge
I just made. This charge here at the very top.
And this is how we can integrate Stripe
to handle payments into our website.
And with that, we now have a real online shop.
Because we now don't just allow users to add
items to a cart, but we then actually
also allow them to make a purchase.
Of course, one thing I would like to fix about the Shop now,
is I want to only show this Buy Products button
if we have items in the cart.
This is not related to payments specifically.
It would have been a good fix before as well.
But, I will add it now at least.
And for this in my Cart views, in cart ejs,
where I do show this form.
I of course want to make sure that I don't just check if
the user is authenticated. But in addition,
I also check if locals.cart.totalQuantity > 0.
If there is nothing in the cart, I don't want to show this.
Now, if I reload, I don't see the button.
Now I just want to tweak the error message a little bit,
because I am logged in.
I will say Log in and add items to the cart to proceed.
So let's save this and reload, and now this looks better.