Created
June 15, 2016 15:05
-
-
Save gbaldera/aa40aa70bc54582e7e8050cadd72470b to your computer and use it in GitHub Desktop.
ASP.NET WebHooks PHP (Codeigniter) Custom Receiver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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'] = '********'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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