When something important happens on an external service (think Stripe), their system can send a
POST request to your app.1 This is called a webhook. Webhooks help automate operations without us having to do anything other than set them up. In this post, I’ll show you how to consume these webhooks with your Rails 5 application.
1. Create a
POST route inside routes.rb.
post '/hooks/:integration_name' => 'webhooks#receive'
Let’s say you’re setting up Stripe. The code above would allow them to post to yoursite.com/hooks/stripe.
2. Generate a webhooks controller with a
rails g controller Webhooks receive
3. Let’s work with the data we receive.
class WebhooksController < ApplicationController skip_before_action :verify_authenticity_token def receive # Parse the data received as JSON data = JSON.parse(request.body.read) # Now you can use the data however you'd like. puts data['xxx'] # Respond that we received the hook head :ok end end
4. Technically, you can be done after Step 3. However, if you’re consuming multiple types of events, wouldn’t it be nice to have a separate action for each one? We can change the
receive method to call a different function for each type of event:3
class WebhooksController < ApplicationController skip_before_action :verify_authenticity_token def receive data = JSON.parse(request.body.read) method = "handle_" + data['type'].tr('.', '_') self.send method, data head :ok end def handle_charge_succeeded(data) # puts data['xxx'] end def handle_charge_failed(data) # puts data['xxx'] end def handle_customer_subscription_created(data) # puts data['xxx'] end end
POSTrequest can contain data about what just happened – i.e. “Customer RSwanson was successfully charged for their monthly subscription.” Your application could consume this data to update RSwanson’s
Alternatively, you could add a
receivemethod to one of your existing controllers. If you do this, you’ll also need to point your route from Step 1 to the appropriate controller. ↩︎