Class: GoCardlessPro::Webhook

Inherits:
Object
  • Object
show all
Defined in:
lib/gocardless_pro/webhook.rb

Defined Under Namespace

Classes: InvalidSignatureError

Class Method Summary collapse

Class Method Details

.parse(options = {}) ⇒ Array<GoCardlessPro::Resources::Event>

Validates that a webhook was genuinely sent by GoCardless using ‘.signature_valid?`, and then parses it into an array of `GoCardlessPro::Resources::Event` objects representing each event included in the webhook

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :request_body (String)

    the request body

  • :signature_header (String)

    the signature included in the request, found in the ‘Webhook-Signature` header

  • :webhook_endpoint_secret (String)

    the webhook endpoint secret for your webhook endpoint, as configured in your GoCardless Dashboard

Returns:

Raises:

  • (InvalidSignatureError)

    if the signature header specified does not match the signature computed using the request body and webhook endpoint secret

  • (ArgumentError)

    if a required keyword argument is not provided or is not of the required type



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/gocardless_pro/webhook.rb', line 24

def parse(options = {})
  validate_options!(options)

  unless signature_valid?(request_body: options[:request_body],
                          signature_header: options[:signature_header],
                          webhook_endpoint_secret: options[:webhook_endpoint_secret])
    raise InvalidSignatureError, "This webhook doesn't appear to be a genuine " \
                                  'webhook from GoCardless, because the signature ' \
                                  "header doesn't match the signature computed" \
                                  ' with your webhook endpoint secret.'
  end

  events = JSON.parse(options[:request_body])['events']

  events.map { |event| Resources::Event.new(event) }
end

.signature_valid?(options = {}) ⇒ Boolean

Validates that a webhook was genuinely sent by GoCardless by computing its signature using the body and your webhook endpoint secret, and comparing that with the signature included in the ‘Webhook-Signature` header

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :request_body (String)

    the request body

  • :signature_header (String)

    the signature included in the request, found in the ‘Webhook-Signature` header

  • :webhook_endpoint_secret (String)

    the webhook endpoint secret for your webhook endpoint, as configured in your GoCardless Dashboard

Returns:

  • (Boolean)

    whether the webhook’s signature is valid

Raises:

  • (ArgumentError)

    if a required keyword argument is not provided or is not of the required type



53
54
55
56
57
58
59
60
61
# File 'lib/gocardless_pro/webhook.rb', line 53

def signature_valid?(options = {})
  validate_options!(options)

  computed_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'),
                                               options[:webhook_endpoint_secret],
                                               options[:request_body])

  secure_compare(options[:signature_header], computed_signature)
end