Class: WebhookInbox::Providers::Stripe

Inherits:
Base
  • Object
show all
Defined in:
lib/webhook_inbox/providers/stripe.rb

Constant Summary collapse

SIG_HEADER =
"HTTP_STRIPE_SIGNATURE"

Instance Method Summary collapse

Instance Method Details

#event_id(raw_body, _request) ⇒ Object



12
13
14
15
16
# File 'lib/webhook_inbox/providers/stripe.rb', line 12

def event_id(raw_body, _request)
  JSON.parse(raw_body)["id"]
rescue JSON::ParserError
  nil
end

#event_type(raw_body, _request) ⇒ Object



18
19
20
21
22
# File 'lib/webhook_inbox/providers/stripe.rb', line 18

def event_type(raw_body, _request)
  JSON.parse(raw_body)["type"] || "unknown"
rescue JSON::ParserError
  "unknown"
end

#verify!(raw_body, request, secret:) ⇒ Object

Stripe signature format: “t=<timestamp>,v1=<hmac>,v0=<hmac>” We verify v1 (HMAC-SHA256 of “timestamp.body” signed with the webhook secret). Raises WebhookInbox::SignatureError if invalid.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/webhook_inbox/providers/stripe.rb', line 27

def verify!(raw_body, request, secret:)
  sig_header = request.env[SIG_HEADER]
  raise WebhookInbox::SignatureError, "Missing Stripe-Signature header" if sig_header.blank?

  parts = sig_header.split(",").each_with_object({}) do |part, hash|
    k, v = part.split("=", 2)
    hash[k] = v if k && v
  end
  timestamp = parts["t"]
  received  = parts["v1"]

  raise WebhookInbox::SignatureError, "Malformed Stripe-Signature header" unless timestamp && received

  signed_payload = "#{timestamp}.#{raw_body}"
  expected = OpenSSL::HMAC.hexdigest("SHA256", secret, signed_payload)

  return if ActiveSupport::SecurityUtils.secure_compare(expected, received)

  raise WebhookInbox::SignatureError, "Stripe signature verification failed"
end