Skip to content

Instantly share code, notes, and snippets.

@subomi
Created January 24, 2021 18:53
Show Gist options
  • Save subomi/98eae370376268f341eaa3f4735a6f47 to your computer and use it in GitHub Desktop.
Save subomi/98eae370376268f341eaa3f4735a6f47 to your computer and use it in GitHub Desktop.
Handle Paystack webhook validation in Ruby.
# Controller to handle Event.
class PaystackController < ApplicationController
skip_before_action :authorize_request, only: :webhook
def webhook
paystack_instance = PaystackObject.instance
valid_event = paystack_instance.verify_webhook_event?(request)
raise StandardError, 'Phony event - Not Paystack' unless valid_event
render status: 200, plain: "Ok\n"
# This works if you have a job system in place.
# Else, keep to handle the transaction before line 10.
body = params.permit!
body = body.to_hash
HandlePaystackWebhookJob.perform_later(body)
end
end
# PaystackObject: This class validates each request, to check
# If it's from Paystack or not.
class PaystackObject
include Singleton
attr_accessor :paystack_obj
WHITELISTED_IPS = ['52.31.139.75', '52.49.173.169', '52.214.14.220'].freeze
def initialize
secret_key = ENV['PAYSTACK_SECRET_KEY'].split(' ')[1]
@paystack_obj = Paystack.new(ENV['PAYSTACK_PUBLIC_KEY'], secret_key)
end
def verify_webhook_event?(request)
verify_ip_address(request.remote_ip) && verify_header_signature(request)
end
private
def verify_ip_address(ip_address)
WHITELISTED_IPS.include?(ip_address)
end
def verify_header_signature(request)
body = request.body.string
hash = OpenSSL::HMAC.hexdigest('SHA512', @paystack_obj.private_key, body)
hash == request.headers['HTTP_X_PAYSTACK_SIGNATURE']
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment