Python for Entrepreneurs Transcripts
Chapter: Making money (credit cards and businesses)
Lecture: Finalizing the purchase

Login or purchase this course to watch this video and the rest of the course contents.
0:01 Let's implement store/complete and finalize our purchase.
0:04 So just because we went through and clicked this and Stripe even said "OK,
0:10 we saw the green checkmark", that didn't charge the card,
0:13 it's not until we go through this final step where the card is actually charged
0:17 and we just got that token that we could finalize
0:19 and do the charge, everything was ready to go
0:21 and it would have more or less worked.
0:24 OK, so, it's over here in this store/complete method that we are going to work with this,
0:31 so let's just start by printing out what get back,
0:35 so remember, we have this data_dict, which is merging all the various dictionaries
0:40 together with the get post the routing and so on,
0:43 so this will show us what gets posted on a successful purchase.
0:46 Let's go and just do this request one more time, so go here,
0:51 I wish I had that "remember me" thing now,
0:58 alright, here we go, posting over, when I get
1:04 "Could not return the valuable callable", that doesn't matter,
1:07 all I want to see actually was what comes right here
1:10 because notice there is no template, no render.
1:13 Alright, before that will happen, check out what we got, this is what we got.
1:19 I am going to put that here for our reference.
1:23 OK, so there is various things, like this comes from the routing,
1:26 obviously we are going to the "complete" method but the two things we care about
1:29 are the stripeToken and stripeEmail probably, so I am just going to make a note,
1:35 we're not going to do anything here, "send email
1:39 receipt", so you want to send the receipt, you want to say
1:41 "hey, thanks for the purchase, here is something for your records"
1:44 to self.datadict of stripeEmail.
1:49 So we are going to want to do that and that's just going to be like a pending to do,
1:52 I am not going to implement it, that's left as an exercise for you guys,
1:55 we already saw how to send templated emails so this is super easy to do.
1:59 But the thing that we want is we are going to get this token here,
2:02 this tok value and we are going to use this in our API.
2:06 We are going to go to our StoreService, and here we can say purchase_album.
2:13 And what does it take, it takes an album,
2:16 it takes a paid amount and it takes a Stripe token, so alright album,
2:20 that is not going to exist, amount paid so this will be album.price,
2:26 and then this will be token.
2:29 Now one thing we want to be really careful of is this amount paid,
2:32 what is this paid in, this is going to be a float so let's say USD.
2:38 Straight dollars, not cents.
2:41 Great, so we are ready to go, notice, there is a few things that we need,
2:48 we need to have the user or at least a user id,
2:51 we could record just the email address and not have this foreign key relationship to our user,
2:56 but maybe we want to make sure you don't have to add it
2:59 to somewhere else that they are logged in.
3:02 So here we could just put self.logged_in_user, for the album,
3:07 how do we get that? Notice there is no information here about the album,
3:11 well, we can pass one more thing, on this route here, we could pass 'id':28,
3:20 the id of the album, and then we could use a query to get that back,
3:24 how do we pass this along? Let's go back to our template that shows the buy button.
3:29 Over here, remember this, right there, we could just do a / and on this we could say
3:35 a.id and then we'll pass the album id.
3:39 That's part of the route, remember, the generic routing we set up
3:42 is always controller action and then this thing called id whatever that means,
3:49 like this last thing we called it id, so let's just double check on the album,
3:53 what comes through there, right,
3:55 the album is an integer, so we'll do a convert there.
3:59 OK, great, so then we are going to have this id,
4:04 and let's go and get that album here.
4:07 So we are going to convert this,
4:12 and we can give it a base sort of default value,
4:16 like minus one or something that won't exist but if this is not there
4:20 instead of crashing we'll just get a "not found".
4:23 So maybe we'll do it like this, album = AlbumService, oops, what do we call it,
4:30 albums plural, and then we can do a find, we don't have a get_album,
4:39 let's say get_album_by_id.
4:44 And we'll write that in a moment, but assuming that works,
4:47 we are going to pass in the logged_in_user, we are going to pass in the album,
4:50 its price and this Stripe token.
4:53 Now, we should probably check whether or not this succeeds
4:56 but we'll deal with that in just a minute,
4:59 let's just say self.redirect('store/success'), down here.
5:04 OK, now this success template doesn't exist, so it's not going to go so well
5:09 but if we see that URL "store/success", we know that things are going pretty good, OK.
5:14 So let's write get_album_by_id really quick, so this should be simple enough,
5:20 session, you want to create a session and then we are going to say query
5:26 or let's just say return and we are going to do session.query of album, filter,
5:34 we're album.id is album_id, and then we'll say .first().
5:40 So that's pretty simple, right, let's make it a slightly more legible like so.
5:48 OK, so we are going to go to the session, do a query for album,
5:52 match by id, that's a primary key so it's either going to be one or zero
5:55 and first we'll return either None or the thing that is there.
6:01 So all of this should work, let's do a little print just to make sure this is working
6:04 print("Finalizing purchase for {} buying {}").
6:08 So self.logged_in_user.name and album.name.
6:21 OK, so this doesn't actually do anything yet, but let's test what we've got so far.
6:27 Oh yeah, remember, this is only going to work if we sign in,
6:31 so let me sign in really quickly. Oh I changed my password,
6:34 I think it's cat now, here, we better update that,
6:37 that's important, OK let's go buy this,
6:40 oh let's do one thing as well, here, let's make this a little bit nicer
6:44 let's go over here and say data-email, self.logged_in_user.email if...
6:56 I forgot what is this base class here, what is it,
7:00 for logged in it is is_logged_in, if that else None.
7:08 OK, so if I try this again of course, view, view is that thing.
7:16 Now I've added the email address, when I click buy
7:21 you could see this is pre populated with the email address tied to my account,
7:25 I can't even edit this if I want, here we go,
7:29 so we go and out all our information and off it would go.
7:33 Before we move on, let me just add that quick check, so this account controller,
7:39 let's go over here, not let them buy this, so we'll go to this form
7:44 and we'll say we are only going to show this form tal:condition="view.is_logged_in".
7:52 Right, if you're logged in, you can see the buy button, otherwise,
7:55 we'd want to add something obviously, so let's say hey you can't buy
7:59 but let's just see how that looks really quick.
8:01 So if we go to albums, we see the buy button,
8:04 if we go to the albums in our private window,
8:07 we should not see the buy buttons, OK, great.
8:10 So now we are guaranteed that we'll have that little message there, cool.
8:14 What I do on Talk Python To Me, or in Talk Python Training is
8:17 you can enter an email address,
8:20 and if I see that there is no account associated with it,
8:24 and you are not logged in, I'll actually create the account for you,
8:27 and then do the purchase associated with your account
8:30 and give you a chance to set a password, or you know,
8:33 you can always reset it through the reset process even if there is no password set,
8:36 so there is a couple of options on how to deal with that right here.
8:40 So let's go ahead and do that final purchase.
8:44 Alright, here we go off to our success, that went through Stripe,
8:49 and bam, "account object has no name", no it doesn't.
8:55 Yeah, so here I have name, I guess this is going to be email,
8:58 that's unfortunate, let's rerun this, let's refresh that, now,
9:02 this form is still like ready to submit, so let's just resend it and see what we get,
9:07 there is errors but "finalizing purchase for mikeckenendy@..."
9:11 buying Digital Age Boys And Girls because remember,
9:14 I am not printing out this thing anymore, but remember,
9:17 we're passing the id of Digital Age Boys And Girls.
9:19 if I go back and I do the other one,
9:22 if I try to buy this one, The Year Of The Snake and it crashes of course
9:28 but that's not what is important, what is important is we have purchasing Year Of The Snake,
9:32 OK so we're passing all this information to the "complete" method.
9:37 What's left? well to record it in the database, and to actually finalize it with Stripe.