ruby 46 lines · 7 steps

How a Rails Stripe webhook controller works

A single endpoint verifies Stripe's signature, dispatches on event type, and answers with the right HTTP status.

Explained by highlit
1class Webhooks::StripeController < ApplicationController
2 skip_before_action :verify_authenticity_token
3 skip_before_action :authenticate_user!
4 
5 def create
6 event = verified_event
7 
8 case event.type
9 when "checkout.session.completed"
10 session = event.data.object
11 order = Order.find_by!(stripe_session_id: session.id)
12 order.mark_paid!(payment_intent: session.payment_intent)
13 OrderMailer.receipt(order).deliver_later
14 when "invoice.payment_failed"
15 subscription = Subscription.find_by(stripe_id: event.data.object.subscription)
16 subscription&.past_due!
17 when "customer.subscription.deleted"
18 subscription = Subscription.find_by(stripe_id: event.data.object.id)
19 subscription&.cancel!
20 else
21 Rails.logger.info("Unhandled Stripe event: #{event.type}")
22 end
23 
24 head :ok
25 rescue JSON::ParserError
26 head :bad_request
27 rescue Stripe::SignatureVerificationError
28 head :unauthorized
29 rescue ActiveRecord::RecordNotFound => e
30 Rails.logger.warn("Stripe webhook target missing: #{e.message}")
31 head :ok
32 end
33 
34 private
35 
36 def verified_event
37 payload = request.body.read
38 signature = request.env["HTTP_STRIPE_SIGNATURE"]
39 
40 Stripe::Webhook.construct_event(
41 payload,
42 signature,
43 Rails.application.credentials.dig(:stripe, :webhook_secret)
44 )
45 end
46end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Always verify a webhook's cryptographic signature before trusting its payload.
  2. 2Return 200 for events you can't act on so the sender stops retrying, but reserve error codes for genuine failures.
  3. 3Dispatching on event type keeps a single endpoint handling many distinct provider events cleanly.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a Rails Stripe webhook controller works — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code