Skip to content

Instantly share code, notes, and snippets.

@gbaldera
Created June 15, 2016 15:05
Show Gist options
  • Save gbaldera/aa40aa70bc54582e7e8050cadd72470b to your computer and use it in GitHub Desktop.
Save gbaldera/aa40aa70bc54582e7e8050cadd72470b to your computer and use it in GitHub Desktop.
ASP.NET WebHooks PHP (Codeigniter) Custom Receiver
<?php defined('BASEPATH') OR exit('No direct script access allowed');
/*
|--------------------------------------------------------------------------
| Secret Key
|--------------------------------------------------------------------------
|
| The secret used to sign the body of the WebHook request
|
*/
$config['webhooks_secret_key'] = '********';
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Webhooks extends CI_Controller
{
private $echoParameter = "echo";
private $signatureHeaderName = "ms-signature";
private $signatureHeaderKey = "sha256";
public function __construct()
{
parent::__construct();
$this->load->config('webhooks');
$this->load->helper('json_helper');
}
public function index()
{
$method = strtolower($this->input->server('REQUEST_METHOD'));
if ($method == "post") {
$this->_verifySignature();
$body = file_get_contents('php://input');
$json = json_decode($body);
if (!$json) {
$this->_createBadRequestResponse(json_last_error_message());
}
foreach ($json->Notifications as $notification) {
switch ($notification->Action) {
case "*":
case "alarms":
$this->_handleAlarms($notification->Alarms);
break;
default:
break;
}
}
} elseif ($method == "get") // verification
{
parse_str($this->input->server('QUERY_STRING'), $queryParameters);
if (!isset($queryParameters[$this->echoParameter]) || empty($queryParameters[$this->echoParameter])) {
$this->_createBadRequestResponse("The WebHook verification request must contain a '{$this->echoParameter}' query parameter which will get echoed back in a successful response.");
}
echo $queryParameters[$this->echoParameter];
}
}
private function _getRequestHeader()
{
$header = $this->input->server("HTTP_" . strtoupper(str_replace('-', '_', $this->signatureHeaderName)));
if (!$header) {
$this->_createBadRequestResponse("Expecting exactly one '{$this->signatureHeaderName}' header field in the WebHook request but found none. Please ensure that the request contains exactly one '{$this->signatureHeaderName}' header field.");
}
return $header;
}
private function _verifySignature()
{
$secret_key = config_item('webhooks_secret_key');
$header = $this->_getRequestHeader();
$values = array_map("trim", explode("=", $header));
if (count($values) != 2 || strcasecmp($values[0], $this->signatureHeaderKey) != 0) {
$this->_createBadRequestResponse("Invalid '{$this->signatureHeaderName}' header value. Expecting a value of '{$this->signatureHeaderKey}=<value>'");
}
$body = file_get_contents('php://input');
$expected_signature = hash_hmac($this->signatureHeaderKey, $body, $secret_key, false);
if (strcasecmp($values[1], $expected_signature) != 0) {
$this->_createBadRequestResponse("The WebHook signature provided by the '{$this->signatureHeaderName}' header field does not match the value expected by the receiver. WebHook request is invalid");
}
}
/**
* @param $message
*/
private function _createBadRequestResponse($message)
{
header('Status: 400', TRUE, 400);
log_message('debug', $message);
exit($message);
}
private function _handleAlarms($alarms)
{
// handle webhook content here
}
}
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
function json_last_error_message(){
$message = 'JSON Error';
switch (json_last_error()) {
case JSON_ERROR_NONE:
$message .= ' - No errors';
break;
case JSON_ERROR_DEPTH:
$message .= ' - Maximum stack depth exceeded';
break;
case JSON_ERROR_STATE_MISMATCH:
$message .= ' - Underflow or the modes mismatch';
break;
case JSON_ERROR_CTRL_CHAR:
$message .= ' - Unexpected control character found';
break;
case JSON_ERROR_SYNTAX:
$message .= ' - Syntax error, malformed JSON';
break;
case JSON_ERROR_UTF8:
$message .= ' - Malformed UTF-8 characters, possibly incorrectly encoded';
break;
default:
$message .= ' - Unknown error';
break;
}
return $message;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment