How to add webhooks to Rails 5

When something important happens on an external service (think Stripe), their system can send a POST request to your app. This POST request 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 account_standing to :active. 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 receive method.

    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.

    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