Working withWebhooks
Lorna Mitchell, Nexmo

What is a Webhook?
An HTTP POST request.

@lornajane

Why Webhooks?
Event-driven HTTP = Webhooks@lornajane

Webhooks in the Wild@lornajane

Slack Integrations@lornajane

GitHub Builds@lornajane

Webhook Use Cases• Notify of events• Deliver data when available• Broadcast to multiple receivers as-it-happens@lornajane

How APIs Work@lornajane

How APIs Work@lornajane

How APIs Work@lornajane

How Webhooks Work@lornajane

How Webhooks Work@lornajane

What About Time?

@lornajane

APIs Over Time@lornajane

Webhooks Over Time@lornajane

Where To Webhook To?

@lornajane

Webhooks Need Pre-arrangement
With APIs, the client calls the server.
With Webhooks, the client has to register with the server, to get data later.
... may also agree security (e.g. shared secret) at this stage.

@lornajane

Receiving Webhooks
Warning: minor tangent ahead@lornajane

Ngrok for Testing Webhooks
https://ngrok.com/ - secure tunnel to your dev platform
Use this tool to:• webhook into code running locally• inspect the request and response of the webhook• replay requests and see the responses@lornajane

Ngrok for Testing Webhooks
Start the tunnel on your laptop: receive a public URL@lornajane

Example: Nexmo SMS
When you register a phone number and receive an SMS, your application
receives a webhook.

@lornajane

I'm running open endpoints on the internet
and accepting data, now what?

@lornajane

Webhook Security
When working with webhooks:• be aware of attack vectors• always use SSL• consider shared secrets and hashing• all good HTTP security practices apply@lornajane

Shared Secrets
Share a secret in advance, then transmit all the fields and a signature hashcreated using the secret.

@lornajaneNexmo SMS Security
Nexmo can sign messages using a shared secret.
The PHP library https://github.com/nexmo/nexmo-php can do this foryou.
$signature = new \Nexmo\Client\Signature($_GET,SIGNATURE_SECRET, 'sha256');$isValid = $signature->check($_GET['sig']);@lornajane

Receiving Webhooks: Best Practice
It's just an HTTP request! Advice:• DO: accept, store and acknowledge quickly• DON'T: process before acknowledging@lornajane

Using Queues in PHP Applications
Queues protect you against bursty traffic.
Queues separate work from webservers.
• This example uses https://beanstalkd.github.io/ and SlimPHP• Other good alternatives: Redis or Laravel Horizon, Amazon SQS,
RabbitMQ@lornajane

SlimPHP and Beanstalkd
1 $container = $app->getContainer();2
3 $container['queue'] = function ($container) {4
return new \Pheanstalk\Pheanstalk(5
getenv('QUEUE_HOST'),
6
getenv('QUEUE_PORT')
7);
8 };

Pro-tip: Try vlucas\phpdotenv for dev platform environment vars.
@lornajane

SlimPHP and Beanstalkd

13 $app->get('/webhooks/inbound-sms', function ($request, $response, $arg
14
$params = $request->getQueryParams();
15
16$data = ["event" => "message",17"text" => $params['text'],
18"receivedAt" => date("U"),19"payload" => $params];
20
error_log("New message: " . $params['text']);21$this->queue->useTube('sms')
22->put(json_encode($data));23 });@lornajane

So The Data is In a Queue. Now What?

@lornajane

Let's talk about Workers
Workers are long-running scripts that process a series of jobs.
Workers need to be independent:• if things go wrong, exit
• separate tool to monitor/restart as needed• beware long-running process hazards• everything processed "at least once" (but maybe more than once, andin any order...)@lornajane

Processing SMS with PHP
14 $queue->watch("sms");15
16 while($job = $queue->reserve()) {17$received = json_decode($job->getData(), true);18
error_log($received['text']);1920// delegate to the class that will do the work
21$worker->process($received);
22
23$queue->delete($job);
24 }@lornajane

Processing SMS with PHP

1 class SecureWorker extends Worker {2public function process($data) {3if ($this->validateMessageSignature($data)) {4$this->write_to_file($this->outfile, $data['text']);5
return true; }6}7protected function validateMessageSignature($data) {8$signature = new \Nexmo\Client\Signature(
9$data['payload'], getenv('NEXMO_API_SIGNATURE_SECRET'), 's
10
return $signature->check($data['payload']['sig']);11}@lornajane

Webhooks... are awesome :)@lornajane

Webhooks in Your Applications• Use them WHEN you want to notify other systems• Examples of HOW to use webhooks hopefully gave you some ideas• Webhooks are HTTP: we already understand this@lornajane

Thanks!
• PHP Web Services from O'Reilly• Me: https://lornajane.net• Nexmo: https://nexmo.com• Ngrok: https://ngrok.com/• Code: https://github.com/lornajane/incoming-sms-beanstalkd-php@lornajane