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


Talk Python's Mastodon Michael Kennedy's Mastodon