Class: Preverus::Webhooks

Inherits:
Object
  • Object
show all
Defined in:
lib/preverus/resources.rb

Instance Method Summary collapse

Instance Method Details

#construct_event(raw_body:, headers:, secret:, tolerance_seconds: 300) ⇒ Object

Raises:

  • (ArgumentError)


71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/preverus/resources.rb', line 71

def construct_event(raw_body:, headers:, secret:, tolerance_seconds: 300)
  timestamp = headers["X-Fraud-Webhook-Timestamp"] || headers["x-fraud-webhook-timestamp"] || ""
  signature = headers["X-Fraud-Webhook-Signature"] || headers["x-fraud-webhook-signature"] || ""
  unless verify(raw_body: raw_body, timestamp: timestamp, signature_header: signature, secret: secret, tolerance_seconds: tolerance_seconds)
    raise ArgumentError, "Invalid Preverus webhook signature."
  end

  payload = JSON.parse(raw_body)
  raise ArgumentError, "Invalid Preverus webhook JSON payload." unless payload.is_a?(Hash)

  WebhookEvent.new(payload, raw_body)
end

#dispatch(event, handlers) ⇒ Object



84
85
86
87
88
89
# File 'lib/preverus/resources.rb', line 84

def dispatch(event, handlers)
  handler = handlers[event.type] || handlers["*"]
  return nil unless handler.respond_to?(:call)

  handler.call(event)
end

#verify(raw_body:, timestamp:, signature_header:, secret:, tolerance_seconds: 300) ⇒ Object



62
63
64
65
66
67
68
69
# File 'lib/preverus/resources.rb', line 62

def verify(raw_body:, timestamp:, signature_header:, secret:, tolerance_seconds: 300)
  return false if timestamp.to_s !~ /\A\d+\z/ || signature_header.to_s.empty? || secret.to_s.empty?
  return false if (Time.now.to_i - timestamp.to_i).abs > tolerance_seconds

  expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{raw_body}")
  received = signature_header.to_s.sub(/\Av1=/, "").strip
  secure_compare(expected, received)
end