2
votes

I just wonder how I could handle webhook from third party API in general.

In my case, I need to handle Webhooks from Stripe.

So I use

  • StripeEvent to handle and listen for the entrance of webhook handlers. It provides an easy to use interface for handling events from Stripe.

The main implementation is:

Everything works so far.

However, let's assume that

  • handling little complex logic within in webhook hanlder
  • listening many webhook requests

In this case, I feel I need to consider to use background job.

Best practices in stripe doc

If your webhook script performs complex logic, or makes network calls, it's possible the script would timeout before Stripe sees its complete execution. For that reason, you may want to have your webhook endpoint immediately acknowledge receipt by returning a 2xx HTTP status code, >and then perform the rest of its duties.

Here is my code, I've just wondered which part I should bundle and enqueue?

StripeEvent.event_retriever = lambda do |params|
  return nil if StripeWebhook.exists?(stripe_id: params[:id])
  StripeWebhook.create!(stripe_id: params[:id])

  return Stripe::Event.construct_from(params.deep_symbolize_keys) if Rails.env.test? # fetching the event from Stripe API

  return Stripe::Event.retrieve(params[:id])
end

StripeEvent.configure do |events|
  events.subscribe 'invoice.created', InvoiceCreated.new # handling the invoice.created event in service object
  events.subscribe 'invoice.payment_succeeded', InvoicePaymentSucceeded.new
 ...
end
1
all of it i guess - phoet

1 Answers

0
votes

Short answer, just send all of it by serializing the Stripe::Event instance to a string with Marshal::dump, then deserialize back to a Stripe::Event in your background worker with Marshal::load.

We also wanted to process the webhook requests in the background using our delayed_job system, which stores the jobs in a database table and the job arguments in a string column.

To do that we first needed to serialize the Stripe::Event to a string in our StripeEvent.configure block:

# event is an instance of Stripe::Event
serialized_event = Marshal::dump(event)

Then we queue the background job rather than handling it synchronously, passing our serialized event as a string to where it is stored (in our case a database table) to await being processed.

Then our background worker code can deserialize the string it reads back to a Stripe::Event:

event = Marshal::load(serialized_event)