WEBVTT

00:00.110 --> 00:06.100
Okay, so we're ready to start creating our new microservice for processing payments for our reservations.

00:06.110 --> 00:13.250
We are going to use the Stripe API to actually bill customers that book reservations using provided

00:13.250 --> 00:14.480
payment details.

00:14.480 --> 00:20.960
We will sign up for Stripe and actually make HTTP calls to the API in this microservice, which will

00:20.960 --> 00:25.430
be calling from the reservation service when a new reservation is created.

00:25.430 --> 00:27.170
So let's go ahead and get started.

00:27.170 --> 00:35.420
Back in the terminal we're going to use the nest CLI as usual to to generate a new app by calling nest

00:35.420 --> 00:36.500
generate app.

00:36.500 --> 00:38.510
And we'll call this payments.

00:38.510 --> 00:47.750
And you can see our newly created payments application was added to our app here and we have the default

00:47.780 --> 00:54.620
controller out of the box here as well as the basic payments module that sets up the payments controller.

00:54.620 --> 00:59.270
So the first thing we're going to do, as we did in our reservations and auth services, we're going

00:59.270 --> 01:06.390
to go ahead and copy over the Docker file from the Reservations app and we'll place it inside of the

01:06.390 --> 01:08.340
newly created payments app.

01:08.340 --> 01:11.700
And the only change we'll make here is in our start up command.

01:11.700 --> 01:17.760
To start the app, we will go into the Dist apps, slash payments folder.

01:17.790 --> 01:20.520
All the rest of the steps will stay the same now.

01:20.520 --> 01:26.760
So now we'll go back in the Docker compose file in the root of our app and we'll just copy over the

01:26.760 --> 01:34.410
existing definition for the auth service, paste it in here and rename this to the payments service.

01:34.410 --> 01:38.520
The contacts is still going to be in the route, except the Docker file now is going to live in the

01:38.520 --> 01:46.050
payments directory and we're going to change the start up command here to NPM run dev payments.

01:46.050 --> 01:50.370
We'll change the file path here to go to slash payments.

01:51.120 --> 01:57.240
And then lastly, we're going to go ahead and expose Port 3003 for the payments microservice, which

01:57.240 --> 01:59.460
will be a TCP microservice.

01:59.460 --> 02:01.650
So we need to specify a TCP port.

02:01.680 --> 02:05.490
We know 3000 is already taken by reservations and an auth.

02:05.490 --> 02:08.220
We have 3001 and 3002 already taken.

02:08.220 --> 02:16.980
So we'll go ahead and map local port 3003 to the TCP port on this microservice 3003 now in the payments

02:16.980 --> 02:23.640
folder, we'll go ahead and create a m file here where we specify a port of 3003.

02:23.670 --> 02:30.000
Now back in the terminal, I'll go ahead and Docker compose up again here where you can see we're going

02:30.000 --> 02:33.780
ahead and starting to build the new payments Docker file.

02:33.780 --> 02:39.030
So after the Docker file is finished building, you can see in our terminal here that our payment service

02:39.030 --> 02:45.060
has started up successfully and the rest of the services now start up being starting up as well.

02:45.060 --> 02:52.080
So now we can go back into the payments directory and we'll open up the Main.ts first where we will

02:52.080 --> 02:56.310
turn this into a microservice, a standalone microservice.

02:56.310 --> 03:03.800
So we'll delete the existing app const here and create a new one where we call Nest await nest factory

03:03.830 --> 03:06.020
dot, create microservice.

03:06.020 --> 03:12.980
And the first argument here will be the payments module as well as the actual options for this microservice.

03:12.980 --> 03:19.910
Firstly, we're going to specify the transport here, which will be transport dot TCP because this is

03:19.910 --> 03:21.650
a TCP microservice.

03:21.650 --> 03:28.130
And then just like we did for the auth microservice, I want to specify the port here out of the config

03:28.130 --> 03:31.340
service which pulls it from the dot m file for the service.

03:31.340 --> 03:34.280
So let's set up our config module in the payments module.

03:34.280 --> 03:40.790
Now we'll go back into the auth module, I'll copy the config module set up here, move it to the payments

03:40.790 --> 03:41.810
module now.

03:41.810 --> 03:49.130
And so we'll go ahead and import the config module from nestjs config as well as importing star as joy

03:49.160 --> 03:56.150
from joy here where we get the schema validation, we're setting the config module to globally here

03:56.180 --> 04:03.090
being available globally and the schema itself is going to specify just the port as we know it.

04:03.090 --> 04:09.540
So we'll go ahead and delete the rest of the entries here and change TCP port to be just port here,

04:09.540 --> 04:11.340
which is a required number.

04:11.340 --> 04:16.260
So now if we follow this approach of creating the microservice, we can't pull the config service out

04:16.260 --> 04:17.880
to get the port environment variable.

04:17.880 --> 04:22.440
So we'll have to follow the same pattern we used for the auth service here where we created the app

04:22.440 --> 04:25.530
and then called get config service.

04:25.530 --> 04:31.890
So let's go ahead and delete the existing app again and we'll call wait nest factory dot create where

04:31.890 --> 04:34.710
we just pass in the payments module.

04:34.710 --> 04:43.800
Then we'll get access to the config service directly by calling app dot get and then passing in the

04:43.800 --> 04:46.980
config service from nestjs config.

04:46.980 --> 04:52.620
And lastly, we'll call app-connect microservice where we'll specify the options here.

04:52.650 --> 04:59.490
The transport again will be transport dot TCP and then we'll have the options object here where we'll

04:59.490 --> 04:59.910
specify.

04:59.980 --> 05:08.860
By the host that we know will be on 0000 to bind to all available IP addresses on the machine and then

05:08.860 --> 05:15.850
the port will come off of config service dot get and we will pull the port off of the config service

05:15.850 --> 05:21.430
like so finally, instead of calling app dot, listen here, we'll change this and call app dot start

05:21.430 --> 05:25.360
all microservices to start up this TCP microservice.

05:25.750 --> 05:31.450
If you look in the terminal, you should see now that the payments logger says that the microservice

05:31.450 --> 05:37.450
successfully started and we'll also go back in the payment module and make sure we import the logger

05:37.450 --> 05:46.660
module from our app slash common directory up top here so that now our logs are nicely formatted with

05:46.660 --> 05:51.490
the correlation ID and other context information from the peanut logger.

05:51.490 --> 06:00.830
And then also don't forget in our main.ts we need to actually call app dot use logger and we pass an

06:00.830 --> 06:08.030
app dot get and pass in the logger from Nestjs Pino here to make sure that our payments app will use

06:08.030 --> 06:09.230
the peanut logger.

06:09.230 --> 06:14.390
And now we should see the payment service using the peanut logger here.

06:14.420 --> 06:14.780
Okay.

06:14.780 --> 06:21.860
So our next step is to actually set up a stripe account so that we can get some API keys and actually

06:21.860 --> 06:27.500
interact with their API and bill our users in our application.

06:27.500 --> 06:33.710
So make sure you head over to Stripe.com and sign up for a new account.

06:33.710 --> 06:41.210
After you sign up for a new account, you'll be able to create a new account within this dashboard here.

06:41.300 --> 06:47.030
I've called Mine here Sleeper and on Sleeper, you can see right now we're in test mode, which will

06:47.030 --> 06:53.060
allow us to make test charges and test this account in a sandbox environment.

06:53.060 --> 06:55.370
And we also have keys down here.

06:55.370 --> 07:02.450
So we have a publishable key as well as a secret key, which we will be using to interact with our API

07:02.480 --> 07:03.680
on our back end.

07:03.680 --> 07:11.480
So after we have our account set up, we are going to go ahead and install the NodeJS Stripe API client

07:11.480 --> 07:16.070
library which will allow us to easily interact with the Stripe API.

07:16.070 --> 07:22.820
So I'll go ahead and do a NPM install stripe here to go ahead and install Stripe and then we'll go ahead

07:22.820 --> 07:25.040
and start our app back up here.

07:25.040 --> 07:32.210
So now inside of our payments folder here in our payments service, let's go ahead and instantiate our

07:32.210 --> 07:40.580
Stripe client by setting up a new private read only variable here that's going to be equal to a new

07:40.580 --> 07:41.780
stripe here.

07:41.780 --> 07:52.010
And we're going to go ahead and import Stripe from Stripe in our imports up top and by default we can

07:52.010 --> 07:54.290
see we need to supply our API key.

07:54.290 --> 08:00.860
So let's go ahead and in our dot env, we're going to set a new environment variable here called Stripe

08:00.860 --> 08:03.040
secret key.

08:03.160 --> 08:08.020
And we are going to pull this secret key off of our stripe dashboard.

08:08.020 --> 08:13.840
So you can go ahead and reveal this secret key here, copy it and paste it in.

08:13.840 --> 08:18.100
So make sure you use your own secret key here because this one will be deactivated.

08:18.100 --> 08:23.560
So now that we have a stripe secret key, let's go into our payments module and firstly make sure that

08:23.560 --> 08:33.190
we're validating that we actually have the Stripe secret key now, which is going to be joy dot string

08:33.190 --> 08:34.390
dot required.

08:34.390 --> 08:37.480
And now in our payment service, let's go ahead.

08:37.480 --> 08:44.590
In our constructor, we'll get access to the private read only config service of type config service

08:44.590 --> 08:50.950
and now we'll move our variable here which we actually need to call Stripe and we'll set this up top

08:51.580 --> 08:53.440
and set it to new stripe.

08:53.440 --> 09:02.630
And now we can use this dot config service dot get and pass in the stripe secret key as our secret key

09:02.660 --> 09:03.260
here.

09:03.530 --> 09:09.350
Parameter here is going to be an options object where we have to specify the API version and this is

09:09.350 --> 09:14.000
going to be the latest version on this current installation.

09:14.000 --> 09:19.370
So it's 2022, 1115 and so now we have our Stripe client fully configured.

09:19.370 --> 09:25.070
If we get some environment validation error here in your back end, make sure you just restart it so

09:25.070 --> 09:28.010
it picks up the new stripe secret key.

09:28.670 --> 09:35.990
Okay, so we're now ready to actually create a charge on a customer's credit card with our Stripe API.

09:36.380 --> 09:43.040
So let's go ahead and in the payment service we'll get rid of the get hello route here and we'll also

09:43.040 --> 09:48.350
go ahead and remove this from the payments controller.

09:48.380 --> 09:50.360
Let's go ahead and remove this route here.

09:50.720 --> 09:57.620
And now we'll go ahead and actually create a new async method called Create charge.

09:57.890 --> 09:59.540
And before we fill out the parameter.

09:59.560 --> 10:00.070
Matters here.

10:00.070 --> 10:02.740
Let's actually look at what we're going to be doing here.

10:02.740 --> 10:10.390
So we're going to be using the payment intents API on Stripe, which is the most modern way to create

10:10.390 --> 10:13.390
a new charge for a customer's credit card.

10:13.420 --> 10:19.280
This is a way we can securely transmit credit card information over the wire and create a one time charge.

10:19.300 --> 10:22.810
So to start, we need to create a new payment method.

10:22.810 --> 10:29.200
So let's go ahead and do that by having a new variable here called payment method.

10:29.200 --> 10:36.940
And we're going to go ahead and call await this dot stripe dot payment methods, and then we're going

10:36.940 --> 10:39.730
to go ahead and create a new payment method here.

10:39.850 --> 10:43.570
So we're going to specify the type here of type card.

10:43.570 --> 10:49.090
And then the next object here is going to be the actual card itself.

10:49.090 --> 10:57.040
And inside of the card object here, we can go ahead and look at the expected card type from the stripe

10:57.070 --> 10:57.910
types here.

10:57.910 --> 11:00.260
So let's go ahead and look at what this will look like.

11:00.260 --> 11:05.960
So you can see all the information here that we're going to need for a credit card, the CVC expiration

11:05.960 --> 11:08.630
expiration year and the number of the card.

11:08.630 --> 11:13.580
So let's go ahead and specify this as the first parameter for our Create charge method.

11:13.580 --> 11:19.580
It's going to be of type card, and this type is going to be the same type of the card here.

11:19.580 --> 11:25.370
It's going to be stripe payment method, create params and we can just go ahead and actually copy this

11:25.370 --> 11:29.630
here and then paste it in here as our parameter stripe payment method.

11:29.630 --> 11:31.370
Create params dot card one.

11:31.370 --> 11:37.820
So we'll go ahead and provide this card as the card property in our payment method here and make sure

11:37.820 --> 11:39.970
we correctly spell payment method.

11:39.980 --> 11:40.280
Okay.

11:40.280 --> 11:45.380
So now that we have the card or the payment method, we're going to go ahead and actually create the

11:45.380 --> 11:46.760
payment intent.

11:46.760 --> 11:54.740
So let's go ahead and create a new payment intent variable that will set equal to await this dot stripe

11:54.740 --> 12:01.340
dot payment intents and we'll call create here where we will pass in the payment method.

12:01.340 --> 12:08.090
And this is where we pass in our payment method.id here so that it will reference this payment method

12:08.090 --> 12:10.640
or this card and charge it appropriately.

12:10.640 --> 12:15.230
So next, we need to supply the amount that we want to charge this particular customer.

12:15.530 --> 12:19.790
And to do that we'll take a new amount parameter here of type number.

12:19.790 --> 12:27.260
And now that we have the amount, we'll supply it here and we multiply this amount times 100 because

12:27.260 --> 12:30.650
by default this will be the smallest unit of currency.

12:30.650 --> 12:33.470
So 100 cents to charge $1.

12:33.470 --> 12:38.000
So it will multiply every supplied value by 100 to get the dollar amount.

12:38.030 --> 12:41.330
Next, we need to supply confirm here and set this to true.

12:41.330 --> 12:47.300
And what this will do is it will immediately confirm the payment intent so that we charge the user right

12:47.300 --> 12:47.870
away.

12:47.870 --> 12:55.280
And then lastly, we're going to have a payment method types option here where we specify the payment

12:55.280 --> 12:57.170
method, type in this case card.

12:57.170 --> 12:59.870
And now I'm also going to supply the currency here.

12:59.870 --> 13:02.030
I'm going to use USD for the currency.

13:02.030 --> 13:04.850
You can feel free to use whatever currency you'd like.

13:04.850 --> 13:11.180
So now that we've successfully charged the user, let's go ahead and simply return the payment intent

13:11.180 --> 13:12.650
back to the caller now.

13:12.650 --> 13:18.290
So now we have everything we need to set up a payment intent and actually bill a user's credit card.

13:18.290 --> 13:24.140
So we know we want to expose this payment service API to our other microservices, particularly our

13:24.140 --> 13:25.730
reservation service.

13:25.850 --> 13:31.130
So as we've done before in our service, in order to expose this microservice functionality, we'll

13:31.130 --> 13:37.100
have a new async route in our payments controller here that we'll go ahead and call create charge.

13:37.100 --> 13:42.440
And this will of course be decorated with the message pattern decorator.

13:42.440 --> 13:46.610
Here we will specify the message pattern of create charge.

13:46.610 --> 13:52.940
Next, we're going to go ahead and extract the payload here, which in this case is what's being passed

13:52.940 --> 13:54.950
to this message pattern.

13:54.950 --> 13:59.690
So we'll go ahead and call this the data and we can actually supply a dedicated type here.

13:59.720 --> 14:05.030
I'll go ahead and create a new DTO folder and inside of the DTO folder, I'll go ahead and have a new

14:05.030 --> 14:12.650
create charged DTO dots and we'll go ahead and export this class of create charge.

14:12.650 --> 14:18.830
DTO now we know the two parameters that the create charge DTO will take and we'll actually take this

14:18.830 --> 14:26.600
from our create charge method where we have these two properties and we'll import Stripe here from Stripe

14:26.600 --> 14:30.620
and we'll just add these two properties to our class here.

14:30.620 --> 14:38.600
So now I'll also go back to the Create charge method and in here we can now just pull the card and the

14:38.600 --> 14:42.620
amount directly off of this type object here of type.

14:42.620 --> 14:46.070
Create charge DTO just to make this a bit cleaner.

14:46.070 --> 14:50.600
And then in the payments controller here, we know that the data will be of type create charge.

14:50.600 --> 14:57.680
DTO and I will return this dot payment service dot create charge and I'll go ahead and pass that data

14:57.680 --> 14:59.450
directly into that method.
