Webhooks in Magento 2

This post explores a short term approach for implementing a webhook in Magento 2. Better support for webhooks is on the backlog, but currently not guaranteed for Magento 2 GA.

So what is a webhook? Put simply, it is when software can be configured to send a HTTP request to a configurable destination (URL) when some event of interest occurs. For example, you might want a webhook called every time a new order is accepted from a customer – there may be an external system you want notified that the new order exists.

So why are webhooks hard to add to Magento? Magento has always had the concept of events, so has a logical place for webhooks to integrate with.

The first issue is more that you would really prefer webhook calls to be performed asynchronously so they do not slow down the main processing flow. You don’t want your PHP code to block because of a slow external URL. This post does not address this issue.

Another issue is events are frequently passed classes. To send data to a remote end point, the relevant data from the class needs to be serialized into some data structure like JSON or XML which is then POSTed to the configured URL. So some serialization code is required. It would be nice if that was configurable, but for this post good old PHP will be used.

So next I thought “great, I will go implement a sample module that implements a webhook by registering an observer that sends a HTTP request to a remote end point”. I thought this could be a useful example to create. Being a good software engineer, my first job was to find some good code to copy and adjust.

You guessed it, the Magento_CacheInvalidate module actually only contains one thing – an observer implementing a webhook notify an external URL when to flush its cache! So much for my grand plans to implement a new sample webhook module.

So how does it work?

First, there is an events.xml file in the etc directory binding various events to functions in the Observer class.

Next, if you look at the Observer constructor you will see a reference to \Magento\Framework\HTTP\Adapter\Curl. The dependency injection framework will provide this instance to your observer for talking to the PHP curl library (a HTTP client library built into PHP).

If you look invalidateVarnish() you will see example code that extracts information from the event to form the data to send to Varnish. It calls sendPurgeRequest() which puts the string into a HTTP header field. This could be easily adjusted to generate a JSON or XML payload instead.

The flushAllCache() function is even simpler. It shows an example of sending a webhook call where nothing is extracted from the event.

This particular example includes a bit of custom logic – there are configuration settings that are used to see if Varnish is enabled that is not required for a normal webhook. The invalidateVarnish() function also joins a few strings to form the correct Varnish header string.

So let’s see how short a webhook could be. I took the flushAllCache() function and stripped all comments and unneeded data structures. Obviously you should not do this in real life, but it helps show the complexity of the code required. I also removed the Varnish specific ‘if enabled’ check. Finally, I made the constructor get the URL from the di.xml file. As you can see, not much code is required to implement a web hook. You do need to add code to extract data from the event if you want to send that data to the end point, but it’s pretty easy to do with PHP with its built in JSON and XML support.

Thanks Alan.
I should have added, my app acts as a 3rd party and will connect to many stores (thus I need the webhooks). So I’m trying to do this via an extension or module. So far I have found one project looking into this @ https://github.com/smile-io/magento2-module-webhook
Thanks