Ruby on Rails starter

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] in this episode we cover foundational topics and dig into the basics of ruby on rails the web framework how it works how we use rails as a base for some stripe developer office hours episodes and also in the stripe samples a collection of github repositories demonstrating integrations with many stripe products you may be just getting started and are curious about how to build an application from scratch to take your first online payment this episode will cover basics to help you get started quickly with ruby on rails if you already have a back end set up and are comfortable adding new routes and are now looking to add a stripe integration you may want to check out other office hours episodes where we show how to integrate specific stripe products and features similarly if you're looking for an introduction to a more like minimal web framework in ruby i'd recommend taking a look at sinatra we have another episode covering getting started with sinatra so why why rails rails is an opinionated feature-rich and popular web framework it includes everything needed to create a database-backed web application demos created with rails allow us to leverage rails conventions and the built-in orm or object relational model to build these data backed demos and they also help us demonstrate things like csrf or cross-site request forgery authentication background jobs sending emails and stuff like that so features that are more challenging to show with minimal web frameworks because while they're possible in a framework like sinatra or express you have to use third-party libraries to solve these same problems if you're already working with a more minimal framework like sinatra or express the same fundamentals we cover in this episode will apply but are implemented a little bit differently across a bigger more opinionated code base today we'll cover setting up a basic front end with the standard built-in html.erb files in another future episode we'll go into more detail about how to set up a front-end framework like react to work with rails it might be helpful to watch and refer to some other episodes before watching this one namely the introduction to the stripe cli as a quick agenda for today what we're going to cover is configuring your api keys and an initializer to get set up we're going to show how to set up a basic front end with a static html file and stripe.js installed and we'll show uh you know working with these dependencies in the gem file implementing some basic routes and connecting those to the front end so you can make requests from your front end to the back end and finally we'll wrap up with a web hook handler or how to set up your web hooks controller so i'm going to start from scratch here in the terminal i'm going to use the rails new command to create a brand new rails application here we're going to call it office hours rails so my preferred database is postgres but rails has several flavors of database that it supports like sqlite mysql etc etc so i'm going to say rails new office hours dash dash database is equal to postgresql i'm going to say dash t to skip tests by default rails uses mini test while i prefer r spec i can also say dash dash skip skip turbo links and dash dash skip listen turbo links is for this is preventing the installation of turbo links preventing the configuration of some dependencies that uh work with the listen gem which has a couple of issues i've noticed with some unix environments so we're just going to skip that okay so this is going to take a moment to install all the dependencies and create all the files we want and some front-end assets okay great our install of the new rails application is complete we're gonna change directory here into office hours rails and i'm just gonna open this up so that we can look at the directory structure so here in uh in the app directory this is where all of your application code will live assets is your javascript css files channels is for um action cable this is if you're doing sort of like real time communication with the front and back end controllers is where your controllers will live rails is an mvc framework model view controller so this is where your controllers live helpers are sort of like mix-ins that you can use with your views and your controllers we probably will not use helpers as part of any office hours episodes you can put some javascript here in this javascript directory um we'll talk much more about this when we talk about front-end frameworks like rails or i'm sorry react or vue or angular etc jobs is where we put the classes responsible for running background tasks so this is like the background jobs directory mailers is for classes that are responsible for sending emails models is our data models the classes that allow us to interact with the database but often times people will put you know plain old ruby objects into these model files and then finally we have a views directory with some template files these are html.erb templates that is embedded ruby on top of html moving on down the list here we've got a config we're going to talk about initializers but in here you'll also notice a master dot key file this file allows us to encrypt and decrypt the credentials file we're going to talk about credential management because we need to set our stripe api keys we also have down here the database which just contains a seeds.rb file common to edit that we probably will not look at or work with anything else that's in here just know that it's there and it's useful and you might encounter some need to change some files elsewhere but for the purposes of developer office hours we're mostly going to be working within that app directory and kind of configuring our initializers and setting up some some basic routes controllers and models let's use the credential management to set our api key we can set an environment variable here called editor and i'm going to set that to vi um this could be your editor of choice visual studio code atom sublime emacs whatever but then the command we run is rails credentials colon edit and this will rails credentials colon edit will decrypt that credentials file this is a just encrypted yaml file so we're going to decrypt it using the master key and this will allow us to edit the yaml and when you save it it'll be re-encrypted so here i can say stripe secret key is my secret key you can find your api keys in the stripe dashboard and we have some episodes about authentication uh where we go in more depth here but generally we'll have three things here a secret key public key and a web hook secret and those are these are sort of my test keys this is how we set up the api keys for the demo your setup may vary and could support multiple environments for for instance production and development or similar so for demos we're always going to just set these test keys at the top level in the yaml block like so all right now if i close this file and save it that will re-encrypt the file so that we have some encrypted credentials next we want to install some dependencies which we can do by opening the gem file which is at the root of the application here at the bottom i'm going to add obviously gem stripe this will install the stripe ruby gem the ruby bindings in the development group i also like to use pry rails and annotate which are a couple of helpful gems for just working in development and then finally we're gonna un comment the bcrypt the bcrypt gem because in some demos we will use bcrypt for encrypting for instance passwords okay we can close the gem file and run bundle install that will install our dependencies when you run a rails application it'll first load the framework in any gems for the application so the gems that we just loaded those will be loaded after the application is loaded then it'll load these files called initializers they live in config initializers you can generally use initializers to hold configuration settings that should be made after all the framework and gems are loaded so for instance setting your api key so here in config initializers there's a directory with several initializers already we want to add a new one called stripe stripe.rb and in here we will globally set our api key to configure the stripe ruby client that way when we make api requests to the stripe api using stripe ruby they will all be authenticated with this globally set api key okay we do this by or we can access the credentials that we set in that yml file by going through rails.application.credentials.stripe because that was the top level key and then we need to index into this with uh the name of the key that was underneath stripe so remember recall that it said stripe and then underneath that we had secret key like this this is what the yaml file looked like so here when we say rails.application.credentials that accesses the file at the top level dot stripe gets us into this level and then by passing in the this symbol here for secret key that'll allow us to pull out the stripe secret key and set that api key so now we can close that all right so at this point we should be able to make api calls to the stripe api so running rails console or simply rails c will give us an interactive shell where we can experiment with objects that are loaded inside of the rails application so the stripe ruby gem should be loaded our api key should be set and we should be able to access and work with the stripe api directly from our terminal so here we can say something like stripe price dot list and you'll see that we get back a list of prices that are connected to my stripe account you can also say something like stripe customer dot create and pass in an email address jenny rosen at example.com i'm not sure why i capitalized the j and are there in that email but you'll see that we do get a response back from the stripe api we just created a brand new customer so we're interacting directly with the stripe api in the in the terminal here in this interactive shell uh through the rails console okay so it looks like uh all of our api keys are configured we've got our dependencies installed everything is working we're able to talk to stripe the final dependency we'll install is stripe.js in rails application there's a there's a file called application.html.erb where the master html layout file is generally the file which wraps all other views and is where we want to install stripe.js so let me show you where that belongs where that lives under apps views layouts there's application.html.erb technically we can install stripe.js anywhere as long as it's loaded before we try to use it it is best practice to load stripe.js on every single page that's why we want to put it in this application html erb i like to put it in the head above these other javascript include tags so i'm going to just add this here this way if we write any javascript in application.js for instance then stripe.js will be loaded first i have also seen folks cut this and put it down below so that it's executing after the body loads this is another practice that i've seen before then you'll notice that when we create other views this yield command is where those like partial templates will be rendered into so this is where we call yield and where most templates are going to render into so first for office hours we typically have this standard html that we put in all templates and that allows us to have a little bit of structure and shape and then that works along with some demo css that we have for all office hours episodes this is excellent now we have like a rough outline of what an application with dependency installed and stripe ruby configured stripe.js configured for us to begin making api calls so next we're going to create a controller and some associated views to see how to handle requests we can say rails generate controller or we can even simplify this to rails g controller orders and say no helper and no assets generally you'll have a model and a controller that kind of have a similar name so if you have an order model you have an orders controller if you have a posts model you'll have a posts controller if you have a customer model you might have a customers controller this is going to generate a new file with a class that's responsible for receiving and responding to requests specifically about orders so rails applications generally follow a very strong convention to help developers build applications faster controllers typically have one or many standard actions but can also have custom routes so let's open up this file and talk about what those standard actions are we have index show new create edit update and destroy okay so index this is where we list items so in this case we're going to be returning a list of orders generally here we return a single item here we return a form for creating an item create is where we actually receive a post request and actually create the item edit returns a form for updating an item and update is where we will receive the post request to change or the put put request patch request to change modify or update an existing item and then destroy just deletes an item okay so this is generally the way that standard actions are set up in rails index new show create edit update destroy so we have this class called orders controller and when we add these actions to the controller in order to route requests to the right controller action we have to update another file called routes.rb it's this configuration file which contains the list of path and controller action mappings so here we have routes.rb this is what it generally looks like to start with there's an entire dsl or domain specific language for defining the routes we're generally going to use this method called resources so you can say resources orders and this is going to create 7 standard path to controller action mappings so by saying resources orders here we will get the orders index so we can say for instance actually i'm going to pull up a graphic that helps explain this a bit more okay so this is in the official rails documentation you see that here it's saying resources photos remember that our controller is called order the orders controller and so when in the demo here it says resources photos and that creates these seven routes a route called slash photos which receives when receiving requests that are using the get http verb those will route to the index action on the photos controller in our case we have resources orders so if you go to slash orders you make a get request to slash orders it will call the order controller index action and return a list of orders that's what it's supposed to be just conventionally separately if you if you do slash order slash new or slash photo new that will be a get request that hits the new route and generally returns a form to create a new order or a new photo we have the same thing with post so if you send a post request to slash photos it will use that create method to create a new photo get with photos slash id so this is like photo slash one photo slash two similarly with orders order slash one order slash two that will use the show method in the photos controller the show action in the photos controller get for slash photo slash id edit this again returns the form for editing or updating the photo this will use the edit method on the controller patch if you send a patch or put request to photo id this will update that photo sending a delete to photo slash id that will destroy that photo so this convention follows for orders and for our controller because we named our controller orders controller and we used this method called resources orders we are able to um out of the box we get these seven methods that we can use and these are the paths to make the requests that will map to those controller actions let's go back to our orders controller here and add a method that will handle requests to the index so if we just say maybe like orders is a list of 1 2 3 4 and 99 and then we say render json of orders this is saying when we receive a request to slash orders because we have we've mapped this in our routes file when we receive a request to slash orders call this index method by default right now we're not going to do anything with the incoming request other than just know that we were asked for a list of orders and then down here we can call render and in this case the the the format that we're rendering back is json and we're passing just an array this array of orders oftentimes if you're working with active record this will be orders equals order dot all and that will fetch all the orders and then return the json for those but for our example right now we don't actually have a model yet so we are simply going to return the json for those orders all right so we've talked a lot about getting our application configured but we haven't yet started the application so we can use rails s or rails server to start the application this will boot up the app by default it's going to use puma for this version of rails and now it's listening on port 3000 so if we went to the browser and went to localhost 3000 and refresh the page you'll get this yay you're on rails sort of default template this is coming from index.html that's in the public directory generally you pretty pretty quick after installing and setting up rails we're going to go back into that routes routes.rb file and configure it so that when we make requests to the root route we receive a different html template so right now if we go to slash orders though we get back the json and uh that's that's all looking great so this is how we can add a method to the server which returns some json in this case orders now if we wanted to we could modify this so that it was maybe it's a list of like keys or uh you know maybe it's an object here maybe we have two objects you know thing is stuff okay all right so now if we come back over here and refresh the page all that json is going to come back just as json in the javascript object uh all right so that is looking that's looking okay it's looking alright so hopefully that helps helps map the methods that are on a controller to the routes file the next thing i wanted to do was create a new controller and this is going to be a very special controller which only handles requests that are coming in for the root route just for the slash so i'm going to say rails g controller static pages i'm going to name the view root so when you're generating a controller you can pass a list of names after the the name of the controller and these will be created as methods on the controller they'll also be created as routes in the routes file so that's that can be that can be helpful no assets okay so we're creating another file here called static pages and it will have a method called root you'll notice that there was also a file here in app view static pages called root.html that we will that we will uh play with in a bit um so let's go to the routes file you'll notice that it added this get request for static pages root we're going to delete that and add root um static pages root root is another special method in the domain specific language for specifying routes where you are just it you can only call it one time and it's just for the the slash so if i remove um orders here i should return the static pages root okay so we've got our we have the root of our application here living at static pages in app view static pages root let's head over here and update this so that our header says developer office hours static pages root so this is what the the the file that was generated because we used the rails g controller static pages and we passed in that root method here we're going to say developer office hours so now we have this root file if we refresh the page you'll see developer office hours that all looks great and this is working as expected now let's go back into the static pages root file and make a button that when clicked will send a post request to create a new order rails g model order and for now let's say that it just has a a stripe id and a status okay so here we can use the again rails generate and this time we're generating a model not a controller so we say rails g model order and then we can pass in all the fields that we want so by default you can also specify a type so if the stripe id was an integer we could specify integer you can also specify string text boolean there's several different ways that you can specify the default is just string so stripe ids are strings statuses are also strings we might have maybe a paid at which is a date time so we can we can do this when we hit enter this will create two things this will create the class file for an order in order.rb and it will also create a migration a database migration for us called create orders the create orders migration is again a dsl or a domain specific language for writing migration so this is going to convert this create table method is going to convert from ruby into the database manipulation language code so the the code that will modify the database by creating a table or updating a table or removing a column or you can create a table called orders it's going to have three column or three columns that we've specified the stripe id status and paydat and then by saying t.timestamps that will add a created at and updated that field automatically for us and rails will keep track of all of those things so by default there's actually a third or a final thing that's created for us by default and that is an id it's an autumn incrementing integer id by default and so all of that will be created for us just by specifying the table like so another thing that we might do is say add index and then you set you pass the name of the table and the column that you want to index on stripe id it might be that we want to look up orders really really frequently with the stripe id and this will by adding an index this will speed up the lookup by making the database more performant we can also add other other options here so we can specify that this should be unique by saying unique true so this this is a pattern that you might see in office hours episodes okay i'm going to close that file and the way that we run this is we say rake db migrate which will run the migration against our database and create a new table in the database so this created a brand new order table i'm not going to go into too much detail about active record but i do want to go back to our orders controller and update this so that rather than rendering the list of items like that we're saying orders is order.all for the index and that should be a good spot for us to start okay so now what we have is uh in our orders controller let's also add a create method here so we're going to say at order is equal to order dot new order params if the order was saved then we want to render the json for the order otherwise we want to render the errors okay so this is super simple you might be wondering where this order params thing came from it doesn't exist yet so we're going to define it down here generally it's a private method on the controller order params this is again just a convention to name it order underscore or like because we're in an orders controller we're going to or name it order underscore preamp if we were in a photos controller we would call it photos underscore params so here we're going to say params.require order dot permit status and paid at and stripe id what we're doing here is specifying which parameters are allowed to be set on an order when we create it so this is how we sort of this is called strong parameters if you want to look up more about the the rails framework and how it's set up this is called strong params for now i'm just gonna sort of wave my hand and let you know that this this is something that you want to do generally this will um mean that the the json or the request that's coming in looks like this order points at and then that's what this required does is requires that there's a top level order key in the params requires a top level order key and then permit status is like paid paid at is some time stamp and the stripe id is you know some payment intent id uh possibly right this this is what the shape of the incoming params could look like so this is uh this is allowing that to be permitted now if we did not want the user to be able to set the stripe id for some reason maybe that's something or we didn't want them to set the status maybe we don't want a user to be able to pass in the status from the front end to automatically mark an order as paid then what we could do is remove status from what's allowed to be set here and instead set it a different way so we can set it by just calling order.status directly on the order method all right so now that we have this order create method let's try to create an order let's try to create an order object so from our front end um in static pages root i want to add a button and for now i'm just going to call it create order and i'm going to add a script tag just in line here where we're going to grab reference to the button so here i'm using document.queryselector and passing in the css selector so the hashtag says refer to these the html element with its id being equal to button or btn and then i'm going to say on click of this button create an order so i'm going to send a post request to slash orders right because our orders we have that slash orders is where we're receiving post requests so a post to slash orders will result in the execution of the orders controller create method because we use this resources orders and the next thing we want to do is we will just we'll just console.log the data that we get back so here we want to pass we want to pass in maybe a status of paid we want to pass in maybe paid at one two three four five six seven eight nine actually let's see df now okay sure that's a little better and then maybe we want to pass in uh the stripe id is pi pi123 okay so this this will make a post request from the client using ajax or using the fetch api when that request gets to the server the server is going to handle it in the orders controller the create method of the orders controller will execute a new order will be created and then saved to the database and we're going to receive the json for the order back then the client will resolve the promise and the data will be this order object let's give it a whirl so if we go back to the browser and click refresh we'll see a new button here and if we open the the developer tools which we can do by right-clicking and going to inspect we can see in the console so there's several tabs here super super helpful if we go to sources we can see the content of the javascript that we have just written if you click on the gutter so on any of the numbers here in the gutter that'll create a break point that will allow us to kind of like inspect the code as it's executing so i'm adding a breakpoint on line 25 because that is right inside of the function callback to the click the click event listener the add event listener method as soon as we click on this button this function should execute so we should hit this breakpoint so when i click on create order it does and it's broke you know the the javascript debugger broke on that line i removed the breakpoint by clicking the line again now i'm going to add another breakpoint to line 39 because the next step here is going to make a post request to this to slash orders to create an order object and then we should get back the order but i've i've skipped one step so it's going to error out but let's see okay so we got an error it says unexpected token here in the console unexpected token uh square bracket at position whatever we got a 422 unprocessable entity that's the the http status code is 422. so if we look at the network tab and click on orders we see this big red error that says action controller invalid authenticity token so in rails they protect from cross site request forgery with this concept of an authenticity token so every request every post request that's received by default should have this authenticity token now there's two things we can do number one we can disable this authenticity token checking not recommended because then you lose your csrf protection which is helpful for preventing fraud preventing people from you know ddosing you preventing several different things just it's it's really important and really common to have csrf checking on a production web application so you want to have it generally turned on the other way we can get around this is by passing the authenticity token in the request that we're sending along so authenticity token is form authenticity token okay so there uh if we include this authenticity underscore token parameter when we're making our request and its value is set to um some string that is available by calling the form authenticity token rails helper method because we're in html.erb we have access to this csrf token and we're able to just put that directly in the code i'm also noticing that i forgot to nest these under order so i'm going to add that too so order is these things okay so all right let's let's try it again if we refresh the page and we go back to sources let's take a look here you'll notice that the authenticity token this string is now filled out right here okay so the authenticity token is again part of preventing csrf i think you can also put it in the header but generally i just put it directly in the request body because rails has this convention of separating out the content that you're sending to create an object as uh by nesting it underneath that key so let's click this button again and see what happens we again have an error this time it's a 500 okay so let's look at the network tab go to orders undefined method or local variable order params order params oh i misspelled it okay so let's go back to our orders controller okay refresh the page click create again all right so now we're in the successful callback here and you'll see that we did get our order back um what's interesting is that uh or like the thing that's of note is that now we have a created at and an updated ad that are full um full timestamps so this was they created that updated at an id are all managed directly by rails and were created for us so now we have this concept of of an order still this order has nothing to do with stripe we are just simply showing how to do crud how to uh make requests from the front end to the back end and vice versa so here we have created in order the next thing i want to do is show how we might fetch orders so let's go back to our static pages root and from here we can add another um some more some more logic here at the bottom so before we do that let's see so at the top of this page i'm going to add a ul with the id of orders and it'll just be empty initially because what we're going to do is fetch the orders using ajax using this fetch api and then we'll populate the list of orders and show just the id and the created at in the list okay so at the bottom of our script here i'm going to grab reference to that orders ul and next i'm going to make a fetch request this time it's a get request so by default fetch if it's a get request you do not need to specify the method or the headers or body or whatever so we're going to make this get request to slash orders and we expect that the data we get back is a list of orders and we'll say something like orders dot for each order and we want to create maybe orders ul dot inner html plus equals um some li uh yeah we'll just we're just kind of playing around here so this is going to be ordered id and from ordered created at and then we'll close the li and this should sort of build up that orders ul as it's going so let's see so if i if we hit refresh here uh we got a 500 uh cool all right so then go to the network tab we come to let's see clear clear let's make sure we're working with the same stuff here so we hit right when the page loads we should be hitting the orders the orders endpoint as a get request and we did and we did get back a list of orders here it looks like those did not actually populate this ul though so let's add some breakpoints here so when we refresh the page this document.queryselector is running let's see the orders ul it seems like it has an id so we're going to fetch orders and then when we get into here for each order orders is a list okay um and then what is order yeah order has that id so enter is it oh you know what i think this might be capitalized all right let's see uh yeah okay cool um so created at all right so refresh the page here and now we have one that's the id of the order from and this is you know the date so this is great if we click create order again uh and then refresh the page we should have a second order i thought uh we're getting errors here what are our errors um record not unique ah the stripe id has to be unique okay so um let's say our stripe id is now um i don't know new date let's see what happens okay so i think we created an order refresh the page okay so now we've got a new order from that date create an order refresh the page we've got order number five all right so this looks like it's totally working um as expected that's kind of how you how you can both send and receive data from the back end that's kind of really the basics for getting started with making requests in rails and kind of all you need to know in terms of the basics for working with rails for developer office hours except for web hooks so let's move on to web hooks last and we'll we'll wrap up by demonstrating how you can work with with web hook with a web hooks controller okay so a web hook is a notification or it's a combination of a bunch of different tools so a web hook consists of a web hook endpoint and web hook notification so when events happen on your stripe account you can be notified of those so a web hook endpoint is this route on your server to which stripe will send post requests we know from creating our orders controller that we can create a create method a method called create in the orders controller and that will receive post requests and that allows us to create order objects similarly with web hooks we can create a webhooks controller and in the create action of our webhooks controller we can receive post requests so i'll say railsg controller webhooks no helper no assets and we don't need any views users do not see any part of a web hook a web hook is purely for some third party to send you a notification so if you go to our web hooks controller here and add a create method this is where we're going to receive post from stripe or another third party okay we need we also need to go to our routes.rb file and set up a a method so we can receive posts to slash webhooks to webhooks create similarly you might see us use resources web hooks only create these two are one in the same so by specifying only that will say only create the routes or only create the paths that will map to one single method that way people you know there's no way to like retrieve web hooks there's no way to see a single instance of an event created from a web hook or similar so what's nice about using resources if is if in the future you decided that you wanted a way to maybe destroy a web hook or something then you could add delete or destroy here or show or something so you could extend this by using resources and just easily adding a new method to that to this this only list all right so we are receiving post requests from stripe here we've got our route set up the way that this works is when we receive a post request from stripe we will generally automate something so when um here there's an entire list of event types here so let's take a look at the event types so under in the api reference under types of events you'll see a huge list of possible event types that are going to happen or be fired on your event so account.updated is an example a balance being available is an example one of the most common is checkout session completed this is a very common webhook event tie for people to automate based on because this is when someone has successfully paid through stripe checkout the stripe hosted checkout page there's several several other events that you might listen for event types that you might listen for and automate based on so for instance you might send an email when an invoice is paid these are the types of things that you would set up web hooks for so we are now going to we're going to build this create method and i'm actually going to start from the web hook controller or the web hook documentation here under check signatures i'm going to go down to the ruby code this code is written in like for sinatra this post do this is for sinatra but the code is quite easy to translate so we'll i'll just copy this and then we can work with this so what does this look like all right so at the beginning we are getting the payload we want to use request.body.read so that we have the most raw version of the payload that's coming in the reason is that we want to do some signature verification of the web hook so down here when we say stripe web hook construct event we pass in the payload a signature header so in the post request that comes from stripe it's going to have this stripe signature in the header and that signature is a a inc when you combine your web hook signing secret with the signature that came from stripe you can double check to make sure that this post request didn't come indeed come from stripe and not some malicious third party who is just kind of sending post requests to your web hook endpoint so our endpoint secret is available in rails credentials under webhook secret because we said this earlier okay if uh deserializing the event fails because it's invalid json we want to render json back to stripe and say error or message e with a 400 status code anything that's not 200 including redirects will result in a failed web hook event from stripes perspective and they will retry we'll retry with exponential back off for several days okay so this is this is where we're extracting the entire raw payload from the request body then we are pulling out the stripe signature header from the request headers request.n allows us to access the headers then we are looking in the rail application credentials for the webhook signing secret that we set earlier here we're setting event we're creating a variable called event and setting it equal to nil so that when we're done with this begin rescue end block we still have access to the event the scope variable scoping in ruby is block block scoping and when you enter a begin block uh the we would lose reference to this variable if we didn't have you know reference in the parent scope so we create the we create event equals nil here so that we have access to the event after we're done with this begin rescue and try catch block okay at the very bottom this is very common we'll have a case statement a case when or a switch where we check um we we switch based on the event type so we're basically saying like if the event type is payment intent succeeded run this block if the event type is payment method attached run this block etc etc so you can really easily add several different event types that you want to listen for let's call that good and then finally we want to render json back that says maybe message just success and that will be rendered back to stripe remember that the the only way that this endpoint is called is directly by stripe one of the things that we talked about earlier was csrf protection or cross-site request forgery protection and uh recall that we passed in the form authenticity token when we were making an ajax call from our front end to our back end so that we knew and we kind of like had confidence that the request the post request that was incoming was from a site that we owned because we rendered that form authenticity token directly into the page and that authenticity token is going to change every time the page loads so because there is no page that's loading on stripes server when they're making a request to our web hooks controller we need to disable csrf protection on the webhooks controller so we can do that with skip before action verify authenticity verify authenticity token so there's this concept of before actions and after actions and rails which are methods that will run sort of before your method is encountered and after your method is encountered and by saying skip before action here we're we're calling this class method at the very top level and passing in the the symbol for the before action that we want to skip over so verify authenticity token is basically just disabling csrf so disable um csrf token checking okay next we want to we're going to use the stripe cli stripe listen dash dash forward to uh localhost 3000 slash hook looks so the stripe cli is a tool for building and testing web hooking or stripe integrations we have a really handy tool in stripe listen that allows you to set up a direct connection between your stripe account and your local machine so that when events happen on your stripe account they're forwarded to your local running web server so we are going to just leave this running in a tab in our terminal and this will form a direct connection in practice when you go to production you'll want to go create a webhook endpoint in the stripe dashboard that points to your production url but in test mode and in development this is really the best way to uh to test and build your web hooks so what we've got going on here is we have this direct connection when an event fires on our stripe account it's going to trigger this listener which will forward a post request to our web hooks controller because again this slash web hooks when we receive a post request to slash webhooks our routes.rb file has specified resources webhooks which matches this webhook's controller name and knows to call the create method so we've got all this set up let's open another tab and there's a separate stripe cli test tool called trigger so i can say stripe trigger checkout dot session dot completed and this will fire several api calls which will result in a checkout.session.completed event firing so several event several other events will also fire so we're going to get checkout session completed payment um you know payment method attached etc etc so if we look in this is the listen tab the tab where we have our stripe listener set up you can see several different events happened here including this checkout session completed event so these are all being forwarded to our web hook endpoint you can see that it was a post request to localhost 3000 webhooks here was the event id that was fired and we got a 200 status code in the response and it tells you like when it when it happened so if we then look in the the server logs for our running application you'll see that we receive these post requests for localhost at this time and it's being processed by the webhooks controllers create method as xml is just the default and here was all the data for the event that was fired from stripe and this allows us to automate things like sending emails or you know pulling from inventory or printing shipping labels or things like that i think i'm gonna wrap it there you should now be uh fully equipped to at least follow along in some of the stripe developer office hours episodes where we use ruby on rails uh and uh yeah some hopefully you were able to take away some best practices in terms of where to set your api key how to manage credentials and a couple other tips and tricks around uh how i work with ruby on rails so please if you have any questions comments concerns reach out we're on irc in the free no network in the stripe channel also happy to chat on twitter at stripe dev or at cjav underscore dev all right until next time
Info
Channel: Stripe Developers
Views: 2,511
Rating: undefined out of 5
Keywords: stripe, payments, rails, ruby, ruby on rails
Id: vULdSKCUhOs
Channel Id: undefined
Length: 49min 58sec (2998 seconds)
Published: Mon Nov 09 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.