WEBVTT

00:00.020 --> 00:02.450
Our next step is to set up the payment service.

00:02.450 --> 00:04.430
So inside Solution Explorer.

00:04.460 --> 00:06.950
Now back to our API functionality.

00:06.950 --> 00:09.860
I'm just going to right click the API and say new folder.

00:09.860 --> 00:12.320
And I'm going to call it services.

00:12.320 --> 00:20.360
And inside the services folder let's just clean things up inside here I'm going to create a new file.

00:20.360 --> 00:25.040
And I'm going to create a class called Payments Service.

00:26.060 --> 00:31.970
And we're typically do this or put something inside a services folder where we're using a third party

00:32.000 --> 00:37.100
service that doesn't rely on our database or Entity Framework or anything like that.

00:37.100 --> 00:38.810
And let's configure this.

00:38.810 --> 00:43.400
So we're going to need to inject inside here our configuration.

00:43.400 --> 00:47.600
So I'm going to use the I configuration interface and call it config.

00:47.630 --> 00:53.990
So that we've got access to the configuration keys that we've just created inside our payment service

00:53.990 --> 00:58.460
class I'm going to create a method a public async task.

00:58.670 --> 01:05.350
And this is going to return a payment intent that we get from the stripe package that we installed.

01:05.800 --> 01:10.330
And for some reason I've got using system and using stripe there.

01:10.450 --> 01:11.770
We'll need the using stripe.

01:11.770 --> 01:15.820
I'm not sure why it's dimmed out, but it is necessary for what we're doing here.

01:15.820 --> 01:22.570
And I'll use the method name of create or update payment intent.

01:22.630 --> 01:30.430
And we'll pass in to this method as an argument, the basket and call it basket, as we're going to

01:30.430 --> 01:35.770
need to see what's inside there in order to work out how much their order is going to be so that we

01:35.770 --> 01:37.300
can notify stripe.

01:37.360 --> 01:41.050
This is how much the customer is intending to pay.

01:41.110 --> 01:48.310
Now we've got the create or update payment intent, because we're not going to stick our user to the

01:48.310 --> 01:50.950
current basket until they've actually paid for it.

01:50.950 --> 01:56.380
So they will have the opportunity to go back into our store, add or remove items.

01:56.380 --> 02:03.540
And when they come back into the checkout, they'll once again hit the endpoint that uses this service

02:03.570 --> 02:05.370
to update the payment intent.

02:05.370 --> 02:06.870
That's the idea here.

02:06.900 --> 02:11.640
Inside this, we're going to use another setting from the stripe package.

02:11.640 --> 02:16.500
And this is going to be for our stripe configuration and the API key.

02:16.650 --> 02:18.840
And we're going to set this to config.

02:18.840 --> 02:26.220
And in square brackets we need to access the stripe settings colon secrets key.

02:26.730 --> 02:28.650
And it's one of those pesky strings.

02:28.650 --> 02:32.130
And once again your typo warning is here.

02:32.130 --> 02:37.590
Please double check that this matches what you've used inside your app settings, whether you've used

02:37.620 --> 02:40.440
Appsettings.json or app settings development.

02:40.590 --> 02:43.380
Jason, please double check that string.

02:43.410 --> 02:47.700
The easiest way for this not to work is to have a typo in there.

02:47.730 --> 02:49.650
Then we're going to create a service.

02:49.650 --> 02:54.660
So I'm going to say var service equals new payment intent service.

02:54.660 --> 02:57.030
Something else that we get from stripe.

02:57.750 --> 03:00.240
And then we'll create an intent.

03:00.240 --> 03:05.220
So we'll use var intent equals new payments intent.

03:05.250 --> 03:07.860
Again something we get from stripe.

03:08.040 --> 03:15.390
And then we can work out our subtotal based on what is contained inside the basket.

03:15.390 --> 03:24.840
So I'll specify var subtotal equals basket dot items dot sum.

03:25.140 --> 03:29.070
And then we can work out how much our basket is worth.

03:29.070 --> 03:39.480
So I'll use x goes two x dot quantity multiplied by x dot product dot price.

03:39.480 --> 03:41.550
And that will give us our subtotal.

03:41.550 --> 03:44.640
And then we can work out our delivery fee based on the subtotal.

03:44.670 --> 03:51.660
Because we know if their order is over $100, then it's going to be free.

03:51.690 --> 03:53.940
Otherwise it's going to be $5.

03:53.940 --> 03:58.170
So the delivery fee will be equal to the subtotal.

03:58.170 --> 04:03.140
And we'll check to see if it's greater than 10,000, which means $100.

04:03.320 --> 04:06.050
And if that is the case, we'll set it to be zero.

04:06.080 --> 04:08.000
Otherwise, it's going to be 500.

04:08.000 --> 04:12.290
And then we can check to see if we already have a payment ID set.

04:12.320 --> 04:16.730
Now what we'll need to do next actually is we'll need to go back to our basket entity.

04:16.730 --> 04:23.120
And we're going to add a couple of things inside here related to payments.

04:23.120 --> 04:32.150
So inside the properties for the basket let's add on a prop that's going to be a string and make it

04:32.150 --> 04:32.780
optional.

04:32.780 --> 04:37.220
And this is going to be a client secret that we'll store inside this basket.

04:37.220 --> 04:43.310
And this is what the client will use to communicate directly with stripe without involvement of our

04:43.340 --> 04:43.880
API.

04:43.910 --> 04:47.720
But we need to get the client secret when we create the payment intent.

04:47.720 --> 04:52.190
And once we have the payment intent, stripe will send us back the payment intent.

04:52.190 --> 04:54.200
And that includes the client secret.

04:54.200 --> 04:56.030
So that we can get this back to the client.

04:56.030 --> 04:57.950
We'll include it with our basket.

04:57.980 --> 05:03.370
Even though it says client secret, it doesn't matter that we're sending it back to the client.

05:03.370 --> 05:07.210
It is supposed to be given to the client to communicate with stripe.

05:07.360 --> 05:11.200
And also we'll have a prop that's a string again optional.

05:11.200 --> 05:15.220
And this can be for the payment intent ID.

05:16.030 --> 05:22.420
And the idea of this one being inside our basket as well is if they do update their payment intent,

05:22.420 --> 05:27.520
or they do update their shopping cart or basket and then they come back to the checkout, then we're

05:27.520 --> 05:30.160
going to need to update the payment intent.

05:30.190 --> 05:36.490
Let stripe know of the new amount based on the changes they've made to the basket, and that will update

05:36.490 --> 05:41.260
the payment intent in stripe so that when the customer does go to pay, everything matches.

05:41.260 --> 05:46.180
Because if there is a mismatch between the amount that we said they were intending to pay and then something's

05:46.180 --> 05:48.700
changed, then the payment won't work.

05:49.090 --> 05:54.460
So we have made a change to an entity, which does mean we're going to need to create a new migration,

05:54.460 --> 05:55.990
but we'll come on to that soon.

05:56.080 --> 06:01.420
So now we have that available, we can continue with our payment service.

06:01.420 --> 06:09.780
And we're going to check to see if the string is null or empty for the basket dot payment intent ID

06:10.200 --> 06:13.230
if it is empty, that means it's a new payment intent.

06:13.230 --> 06:15.900
So we'll create the configuration for that.

06:15.900 --> 06:17.820
And we need to create some options.

06:17.820 --> 06:24.330
So I'll say var options equals new payment intent creates options.

06:24.570 --> 06:26.430
And we'll open curly brackets.

06:26.430 --> 06:28.380
And then we'll specify an amount.

06:28.380 --> 06:32.730
And that's going to be equal to the subtotal plus the delivery fee.

06:33.600 --> 06:41.220
We'll also need to specify the currency which we'll set to USD in this case and the payment method types

06:41.400 --> 06:44.670
we will specify in square brackets.

06:44.670 --> 06:47.670
And then quotes is going to be card.

06:47.700 --> 06:52.320
That's the payment type that we are going to accept for our application.

06:52.320 --> 07:03.290
And then we can use intents equals and then use await service and create async to create that payment

07:03.290 --> 07:06.290
intent and we need to pass it the options.

07:06.860 --> 07:12.530
And what this returns to us is a payment intent from stripe.

07:12.590 --> 07:14.570
We'll also add the else condition.

07:14.570 --> 07:21.020
So below that curly brackets we'll add else open curly brackets again and create some options for if

07:21.050 --> 07:22.940
we're updating a payment intent.

07:22.970 --> 07:25.310
So I'll use options here again.

07:25.310 --> 07:31.850
And this will be new payment intent update options.

07:31.880 --> 07:38.450
And all we need to do here is double check the amount and set the amount based on what they've updated

07:38.450 --> 07:38.870
it to.

07:38.900 --> 07:44.660
So we'll use amount equals subtotal plus delivery fee inside here.

07:44.660 --> 07:48.740
And we don't need to set anything else because the currency and payment method types well they're not

07:48.740 --> 07:49.640
going to change.

07:49.670 --> 07:56.210
And then we can use await service and update async.

07:56.210 --> 08:02.570
And we'll pass in the basket and the payment intent ID and the options for this method.

08:02.570 --> 08:07.160
and below the else statement we can return the intent.

08:07.160 --> 08:09.770
And that's the code for the service complete.

08:09.770 --> 08:14.870
And because it is a service, then we're going to add this to our program class so that we can use it

08:14.870 --> 08:19.010
inside our controller and inject it inside our controller.

08:19.010 --> 08:21.680
So we'll open up the program class next.

08:21.680 --> 08:25.700
And inside here inside where we're defining our services.

08:25.700 --> 08:28.490
And because it's a service we can put it wherever we want.

08:28.520 --> 08:34.070
I'll just add it below the middleware because I feel that's the cleanest tidiest place to add it, not

08:34.070 --> 08:35.390
because I have to put it here.

08:35.390 --> 08:37.760
And then I'll specify builder services.

08:37.760 --> 08:40.340
And this one we're going to use add scoped.

08:40.340 --> 08:44.690
And remember the scoped is scoped to the HTTP request.

08:44.690 --> 08:51.950
So when the HTTP request is received and it's going to the payments controller that we don't have yet,

08:52.130 --> 08:56.900
the payments controller will have this payment service injected into it.

08:57.230 --> 09:03.940
And when the payment controller is created by the framework, then it also creates a new instance of

09:03.940 --> 09:08.470
our payment service that we're adding inside here.

09:08.470 --> 09:14.860
And because we've updated our basket entity, that means we also need a new migration.

09:14.860 --> 09:16.510
So I'm just going to open up the terminal.

09:16.540 --> 09:19.120
Go back to the tab where I'm running the API.

09:19.150 --> 09:31.330
I'm just going to stop it and clear this window and say dotnet new or dotnet f migrations ads and just

09:31.330 --> 09:36.010
say basket entity updated and press return.

09:36.010 --> 09:39.160
And this should work without issue and it has done so.

09:39.160 --> 09:40.660
Let's go and check the new migration.

09:40.660 --> 09:43.720
Just make sure we see what we expect to see.

09:43.750 --> 09:45.430
Please always do this.

09:45.430 --> 09:50.620
Please don't assume that just because it looks like it worked, it has worked.

09:50.620 --> 09:55.570
And what we'd expect to see in here is the two columns being added, the client secret and the payment

09:55.570 --> 09:56.500
intent ID.

09:56.830 --> 09:57.850
So that looks good.

09:57.850 --> 10:04.300
And the next thing we'll take a look at is adding a payments controller that makes use of this service.
