Buy Now Button with Stripe API and Rails

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay so what I'm gonna do here is I'm gonna go back to my master branch so we're sort of like back in time for when we didn't have a shopping cart functionality implemented at all and now I'm gonna implement a slightly different thing I'm just gonna implement like a Buy Now button that's on an individual product so again I'm not implementing the thing that you would necessarily need to finish your project requirement for checkout but it's gonna show you a lot of that the same ideas but it's gonna be just for purchasing an individual product rather than a collection of products and again just just thinking back to the shopping cart that we implemented for the project you have to bring in the concept of quantities so you can't just be saving the IDS in an array in session if you're gonna go this session route you'll probably need to be saving like a hash into that session array that contains both the ID and the quantity and if the items already in there you like increment the quantity or modify that quantity so it is a little bit more complicated than what I initially implemented okay so we're gonna use stripe to implement our payment processing so stripes just a company that has an API for for payments you hook in you know your bank account details and you can start taking payments by way of stripe their business model is that they they skim off like 3% plus $0.30 or for every payment that you that you make similar to what credit cards charge they have a really nice API and they have documented their API really really well and that I've heard an interview with one of the creators of the company this is now like a billion dollar company and their initial whole game plan was to bring this out and target developers to make it like as easy as possible for developers to integrate this into their system because they were going up against some really really big players like PayPal for example that's been around for years and years and was sort of seen as like the de facto standard but PayPal documentation is not very good like their developer documentation and their API because it's built up over a number of years it's a little clunky and so yeah so they've specifically build stripe around this idea of like maketing making it as developer friendly as possible and there used to be I go to the stripe dogs there used to be like I think I'll check out with rails that was this really nice you know it did didn't didn't take much time to implement there there's a gem we're still gonna use that gem and you would you know you'd have this check out button and it would pop up right within your application like a little payment field a little modal and you'd fill it out and you click Submit and then it would tell you if the payment went through by way of an API request that's now considered legacy it still works so if you go look up my old videos on YouTube you can see the old videos that I've created using this legacy process if you still want to use the legacy process just due to its simplicity for your project you can just know that it's no longer the sort of the way that you're supposed to do a stripe and I can't guarantee how long it's going to be around for it this way I imagine they probably have to persist it for a while because they don't want to have vendors that suddenly can't take payments but yeah I'm not gonna be showing you that I only discovered that it that it went legacy during class on on Monday because it went legacy right after the last run of this course in in April 2000 nineteen so between Monday and today I sort of played around and figured out how to do it in in sort of the new way so that's what I'm going to show you today I would recommend just watching and not trying to code along just in that like I'll probably be stumbling around trying to get this thing to work and so yeah so we'll just we'll go with that so I'm gonna start by adding the stripe gem I'll first start by check out - be stripe integration I'm gonna go to my gem file I'm gonna add the stripe gem and then I'm gonna do a bundle install install and the gem it does the it simplifies communicating with the API for you so you can communicate with the API just with raw HTTP calls but having the they're built in gem is it's really nice stripe itself is a ruby application it's not a rails application but the entire stripe infrastructure is is just a it's a big ruby app and it got so big that they felt the need that they wanted types in their system like the one downside to the all the flexibility that ruby offers you is that there's no type system so the engineers at stripe have actually built a type system that they bolted on to Ruby and they're in talks now with the core group that actually implements the Ruby language to actually get that type system brought in to the Ruby language maybe as an optional typing system maybe going forward as like yeah the ability to annotate types if you want to anyways it's interesting to see that they they were able to build a multi-billion dollar company around an application that that didn't have types and then realized what we really want some type safety here and then they they bolted that on to the project and open sourced it now so you can you can play around with it yeah okay so that's that's there I'm going to go into my config folder and there's an initializers folder and I'm going to create a new file in there and I'm just gonna call it stripe that RB any file in this initializers folder is just going to be executed on server initialization so it's like a place where we can set stuff up and so what I specifically want to set stuff up is stripe gives me two API keys a publishable key and a secret key and this is how you communicate with stripe with the API you never give stripe your secret key but you tell the story PAP a what your publishable key does and then it can encrypt stuff that only you can decrypt with your secret key hence it knows who you are and you never want to put these kind of keys into your github repository especially if you're pushing your repo up into a public repository so I'm gonna let y'all see my secret key because I don't have any bit Thank You G jealous this is you but this look out so it's fine and you know I'm publishing this on on YouTube so now the world gets to see my secret key I will cycle my key after after this video but it is just it's just the test key so I mean I'm in test mode and in test mode there's just one credit card that actually works and it's just the number 42 repeated over and over again still I'd still don't want to put these into my repo what I want to do is I want to put them into environment variables at the operating system level and then pull those in at runtime from my cold and so I'm gonna do that like this I'm gonna go to the Rails object and inside of the rails object we have this configuration object where we can support configuration stuff and inside of there I'm going to put in my publishable key as a key and the way that rails can read environment variables from the OS is we have a special hash called env and it's just going to talk to your operating system and say give me the environment variable that you have at the operating system level called in this case publish able key and same thing goes for secret key we're gonna stash that in an environment variable called secret key and then I'm going to go to the stripe gem and set the secret key should be the one that I just put into here a position secret what that means is I now need to run my server with the provision of passing at a key the easiest way to set up temporary environment variables in a Linux environment is just to set them right before you call the rails command and so this is all on one line I'm saying publishable key equals and there's my public key I'm saying secret key equals and there's my secret key space rails s and so for the invocation of rails s both of those things will be available as environment variables and when the server boots up it'll stash them into this striped configuration and it'll take the secret key specifically and hand it over to the striped gem so that when I start communicating with the API that secret key will already be in place so that is step one the next step is my routes I want a few routes these aren't really gonna be restful roads because I'm not really dealing with like a resource like a model that's on my end and so I'm gonna use what's called the scope and I'm gonna put them all inside the check out scope meaning that they'll all start with slash check out and then I'm gonna create a few different routes one's going to be called create this is gonna create a check out I want it to go to some kind of check out controller that doesn't yet exist and check out eh and then stripe also asks you to have two routes available on your website one called cancel one called success and it's going to redirect the user back to those well it's depending on if they cancelled their process or if it was successful the new way of handling stripe is instead of a modal popping up right within your application when we go to pay it's gonna take us away just a stripe page pay there and then it'll redirect the user back to our website after the fact and it will redirect to one of these two routes the cancel wrote as check o cancel or the successful counseling I did oh yeah so those are the routes that are going to be in my system I can see them I go to rail slush info just make sure that I didn't typo anything there I have the check out create path to check out cancel path and the check out success path two of them are get requests that go to the correct actions and one is a post request that also goes to the correct action that's good that makes me happy okay rails generate a controller called checkout that has a Vista no that's not what I wanted success cancel reactions and what I would like is just like I did for the add to cart' I want there to be like a little button here where I click on it and I can like buy now buy a particular product right now so I will I'll do that I'll do a button to all by now and that's going to go to my checkout create path I think by default the button is a post but I will just ensure that it is a post and I need to echo that out I know so clicking on this great I say great because nothing broke didn't do anything by default the the button to is going to try to make that submission sort of behind the scenes it's gonna do it by way of like an ajax request and that's that's fine that's how I want things to be maybe i'll just make sure that behind the scenes here it didn't like do anything weird network wise yeah okay so a post request what's on uh-oh Jeremy that's good we currently aren't and this is an instance where I can send it because my route doesn't know the product my route doesn't have an ID in it so here I can show the other way of doing things the way that I was trying to do them before so again I could send the ID in one of two ways I could make it part of the URL or I could send it as part of a parameter prams ID product yeah let me see if that's the thing clickety clack I click on it I look here what are you sending perhaps id6 yeah okay so now I'm actually so it's like I'm submitting a form in fact it's not just like I'm submitting a form I am submitting a form there's one of the forms right here and that form contains a hidden input where that ID is being submitted so a slightly different way we could have done the exact same way as we did with the add to cart' by putting the ID into the into the URL there's there's different opinions on whether you should use the URL for those kind of things or perhaps for those kind of things I don't have a strong opinion on either side of that debate okay so that that's going to hit my check out controller I don't need my product so I don't need this I don't need that anymore or that's gonna hit this right here what I need that to do there's my cheat sheet here when I click those buttons it happened behind the scenes that's because it was being submitted like in an AJAX way rails has this neat thing where you can actually respond to different formats I can have a respond to format and you may have seen this if you looked into like a scaffolded controller this is how rails has like the separate kind of responses for HTML versus JSON it also has a response which is server generated JavaScript and it's so it's gonna be a file that's gonna be jst RB and so it's going to be actually a JavaScript file that we can have embedded Ruby inside of so that we can inject dynamic stuff from Ruby into our JavaScript before we serve it out to the browser and so I'm gonna say here format J s and what this is gonna do is instead of trying to at the end of this thing render a phd ml d RB it's gonna render a create dot JSP Rd and then at the top here I'm gonna go find the product in question from the params that I've been given and that product variable should be available inside of this create jst RB so I need to make that file it goes inside of my check out folder in the views create dot j SE r b and just to have something working I'm gonna do a console log and this is gonna look weird but I'm going to do that I'm gonna run some ER be inside of this JavaScript the CRV is not running in the browser it's running on the server generating the JavaScript that is then sent to the browser that is executed so what should happen is it should from the controller pick up the product and inject the products name into a console log I also want like a bit of a guard here so that if someone's like messing around with my site in a way that I don't want them to like if a prams that gets sent that doesn't actually result in a product that I just want to redirect to a root path and then return from this function and not try to do any checkout functionality so I do a little bit more defensive like programming when I'm dealing with things like monetary things just because those are likely the things that people might try to monkey around with so I won't even like what's gonna happen here in between this and this is I'm eventually going to start setting up a stripe session or a mint and so I won't even bother doing that if I don't have a product to buy at all so let's see if this if this does what it's supposed to do I'm going to reload this page I'm gonna bring up my JavaScript console I'm gonna click buy now on my rustic bronze chair yikes that didn't quite work undefined local variable product in your chicken controller did you meet product I did I did I did mean product thank you for being so helpful back over here rustic bronze chair oops rustic bronze chair look unknown format why don't you like done by now button method is post do I have to explicitly say remote true clack yeah look at that ergonomic iron knife and click this one I get the next one so I've successfully handed the ID of the product over to the controller by way of an ajax request i've dynamically created some JavaScript that uses ER b to inject the product name into a console log and delivered that javascript to the browser this can also be done there's some really neat stuff you can do with this pattern that gives you some of the reactivity that's something like react review would give you without having to breathe bring in react in view because inside of here there's a way of like actually getting JavaScript to render partials for you that are your actual like rails partials and so you can click on something and then have pieces of the page just using the Dom change and so that's how when I want used to want dynamic aspects to my website that's how I used to to implement them and it's still I give you if you don't need all of the power of reactor view you can do a lot of really powerful things with this server generated JavaScript that that we get ok what do I need to do now well now I need to communicate with the stripe API ok so the way that the stripe API is going to work is before I shuffle the user off to a website for them to actually pay I need to connect to the stripe API and say I need to set up a session stripe API for a person to make a purchase and this is what they want to purchase and this is how much it costs and their payment method should be XYZ so that's what I have to do now so I'm going to do that like this I'm going to say session equals I'm going to go to stripe checkout session dot create and I'm gonna say that the payment method types and we could put other types in but I only want to pay by card in this case and then line items like what is this user actually purchasing and in this case while they're purchasing a product that has a name and I just description which is a product that has a description I actually don't even need this thing to be an instance variable anymore cuz I'm not gonna use it in my JavaScript anymore so I can like get rid of that and then over here this thing could just be a regular old variable I have images for these and you could even tell stripe the image and when it goes to the separate stripe page it'll display the image as well but for that to work I can't just be running a local host because for that to work stripe wants to actually hit a live server download the image and cache it and that's not gonna work as I don't have a live server so I won't pass the image I will pass the amount that I want this product to be and this is where stripe wants the amount in cents and the currency needs to be Canadian dollars and the quantity is just gonna be one yeah that's good so those are my line items and finally I gotta set up the success URL and the cancel URL and those well I have to find those in my routes alright I have checkout cancel and check-out success so check out success and I if I use path I just get the relative path if I use URL I get the full URL including the HTTP in the domains that's what I want and then check oh and this needs to be a comma there that looks pretty good let me just look it over payment method types there's a single line item which is a hash inside of an array success and cancel and then I'm being shuffled off to this create and so actually inside of this create I need something else where is it on my cheat sheet here here it is setting up a variable cost stripe equals stripe and so we're in JavaScript mode by bringing in that gem we also get access to some drip stripe JavaScript and I'm going to inject into that my publishable key so remember that's the thing I stashed away earlier in this configuration object apposition publishable key and so that is getting put into string there and now I can go to this stripe object and I can save redirect to checkout and I've made this session and instance variable and I need to specify here the session ID and again you're be echoing so it's handy that we have this ability to echo into JavaScript close that this sends a promise back to me that if things go wrong I'm supposed to like let my users know what went wrong in the process for the sake of this demo I'm just gonna do a console dot log which is not a good way to let your users know what's going on there you are and I think that's all I need in this javascript setting up the publishable key to create the stripe object asking stripe to redirect to check out with the session ID that was set up inside of my controller and that's something in place for if things go sideways I want to buy my organ I'm a guy our knife look at that it brings in that information ergonomic iron knife there's the price there's the description the image should be there if I had provisioned an image I can give it my email address wali button example.com give it a that's the testing credit card that they give you that always works as long as you put in a date in the future and any confirmation number put a postal code in and I can click hey wait a second do I have a success page for it to return to I have a success that but I don't have a view for success we took your money very professional that was saved yeah click this button da we took the money if I go back to the dashboard and I go to my home here this is the stripe dashboard look at how much money I made today just dollar dollar bills and so I could go into the payments I could see the session that I just set up and I can see that it was successful these incomplete sessions so there's a side effect here is if someone starts the process but they don't complete it you get an incomplete session that gets garbage collected after I think 24 or 48 hours and I can click in here and I can see that it was an ergonomic iron knife that was purchased and the price etc there are some downsides though one of the downsides is we get to this idea here if we took your money but my rails application doesn't know that things were successful really it sort of knows that the success thing happened but there there are some ways around this the recommended way is to use what's called a web hook and what a web hook is is I would set up a route on my rails app that is not for users but is for stripe and so I would go into stripe and I would set up a web hook saying okay I have an endpoint that I want strike to hit whenever payments come through successfully and stripe would hit that and I would be able to say okay it would deliver like a payload to me that would be some information around you know the purchase that just went through and then I could actually go in and stamp that thing as as paid in development mode though I'm on localhost so stripe can't just hit a web hook in some of the docs that I found they recommended in croc which I had never heard about before but looks super cool what end rock does is it it provides a tunnel for you it gives you a public facing domain that will tunnel through to your localhost so you could set up a web hook at at stripe with an end Rock address that would then tunnel through for you but then I also found that stripe has a command line tool up on github and the thing that this command line tool will do is you can use it as a proxy for for the web hook so you can sort of run it locally you give it your public key it connects to stripe and says let's establish a testing web hook and it would it would work that way as well the way I'm gonna show you a way that just really quickly that's a little bit sketchy I would never use this for a production site but it would get the job done and so what this the idea behind this is is if you want on success here you can add something to this URL you can add to your success URL a question mark session ID equals checkout session ID what that means is when it redirects back to your success page it will redirect back with its internal session ID for you and then over here on the success page I can load that session up I could go to the session I could go to the stripe session and I could retrieve on the params hash the session ID and then given that session ID I can grab what's called a payment intent which basically tells me whether or not this payment went through how much money was paid it even gives like a almost like a confidence rating on the credit card like this this credit card looks sketchy or not kind of credit card rating and so I can do a stripe payment in ghent and dot retrieve using the sessions payment intent in this is an alternative the webhooks not recommended because it relies on the user being shuffled back by way of a redirect if the user like quickly closes their browser or they're on a train that goes through a tunnel and suddenly in the network drops like there's all sorts of things that could make it so that that doesn't happen that they don't actually get redirected back so you would never want to rely on this to like stamp something it's paid you would always really want to do the webhook route I'm just showing this because if someone wants to be a more of a completionist on the project and actually like figure out that this thing is going through and they don't want to go to the extent of doing all the web hook work this this would be enough to show that you can at least get that information back and so on success here I'm just going to output a few things I'm gonna do a debug on the session that I just grabbed and on the payment intent so let me just see session stripe checkout session retrieve params at session ID that should be coming from here and then payment intent is stripe payment intend retrieve and then I get the payment intent from the session so let's try to buy let's try to buy another thing on my store here some intelligent iron shoes head on over here be a pay this is the session that was returned back from stripe it's got a lot of junk in it but you can see things like this is how much money I requested if I go down to the payment intent that's this one here we can see not only the amount that was requested but the amount that was retrieved and so I could now check in my system if I just got what I asked for did I just asked before eight five seven six five cents from the customer and if I did you know things went through I would also check to see I think there's like you know paid true was just a boolean to see you know that this user paid or not at this point I would do things like within here and within here this this session stripe is going to give me their internal customer ID I would probably save that into my database there's gonna be a transaction ID which could just be this payment in ten I'm gonna say that to my database so I would go and save a bunch of those things to my database but I would also check to see if that payment actually went through by peeking at this payment and content but again this is not a real world solution to the problem the real world solution to the problem would be to use the webhooks because that would be much more stable than this there's all sorts of things that could go wrong but you can see here that's how I got that information back when stripe redirected me back to the success by having this little snippet at the end of that URL the stripe API put the session ID in the URL for me as a URL parameter of the called session ID that's what gave me the ability to retrieve the session ID from the params hash and look it up and then from the session ID I was able to find the payment intent and again I was able to figure this all out this week really quickly just based on how great their dogs were that their dogs are just really really nice in terms of yeah showing you how to do all all the things and so it was like the checkout Docs that I was working through specifically the one-time payment ones and anytime they mentioned the API directly it takes you over to the the actual API there's like full payloads completely documented and for any of the endpoints it gives you like the Ruby code that you need to interact with the endpoints or like you could how to interact with it with command line curl or if you're working with their Python library or if you're working with their PHP library or if you're working with their Java library you see what I mean about developers they're targeting developers here they want this to be the absolute easiest way so that a dev says well what's the least amount of work that I have to do today to get payment processing you know for my company to work and they're gonna go to stripe and say hey that's pretty easy I can just copy and paste this code right into my code and I'm done and so yeah I think they're their business model was was really really successful so that's all I got for you for today I'll put all this code up on github I'll put up the two brand choose the branch where I implemented the session-based cart and I'll put the branch where I implemented this checkout functionality again this check of functionality is not complete or the one final thing I will mention it for the project you also have to do taxes right and so I won't bother implementing this now but one of the things I did before is you could actually make taxes as a separate line item right because you can put multiple line items in here right so I could add a second line item here with a name of like PST and a description of like provincial sales tax and then I could just straight up in line here calculate what that PST value is do the same thing for GST as the line item and suddenly I've added tax saying it's gonna sum it all up properly for me at that checkout time and so that's a way of implementing the collection of taxes into this way of handling stripe because it'll just be a line item for each of your taxes or for you know those that apply depending on the province did you have a question shop no just resting your hand all good so thanks for coming to class today and listening to me talk about session and stripe
Info
Channel: Kyle Geske
Views: 4,745
Rating: undefined out of 5
Keywords: Stripe, Ruby, Rails, Ruby on Rails, RubyOnRails, Stripe API, Stripe Checkout
Id: iZgYeyzEMj0
Channel Id: undefined
Length: 42min 59sec (2579 seconds)
Published: Wed Nov 20 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.