main
rb 45 lines 1.49 KB
Raw
1 # frozen_string_literal: true
2
3 # Receives Stripe webhooks for siGit Code billing and syncs the local
4 # Subscription cache. Public endpoint, authenticated by the Stripe signature —
5 # never a user token.
6 class StripeWebhooksController < ActionController::API
7 def create
8 payload = request.body.read
9 signature = request.headers["Stripe-Signature"]
10
11 event =
12 begin
13 StripeService.construct_event(payload, signature)
14 rescue JSON::ParserError, Stripe::SignatureVerificationError => e
15 Rails.logger.warn("Stripe webhook rejected: #{e.class}: #{e.message}")
16 return head :bad_request
17 rescue KeyError
18 Rails.logger.error("Stripe webhook secret not configured")
19 return head :service_unavailable
20 end
21
22 handle(event)
23 head :ok
24 rescue StandardError => e
25 Rails.logger.error("Stripe webhook handling failed: #{e.message}")
26 head :ok # ack so Stripe doesn't retry a poison event forever; we logged it
27 end
28
29 private
30
31 def handle(event)
32 case event.type
33 when "checkout.session.completed"
34 session = event.data.object
35 subscription_id = session.subscription
36 StripeService.sync_subscription(Stripe::Subscription.retrieve(subscription_id)) if subscription_id
37 when "customer.subscription.created",
38 "customer.subscription.updated",
39 "customer.subscription.deleted"
40 StripeService.sync_subscription(event.data.object)
41 else
42 Rails.logger.debug("Stripe webhook ignored: #{event.type}")
43 end
44 end
45 end