0

My question is how to read header information with php received from other site. (I'm using patreon webhooks) The documentation page says:

When one of these events occurs, our servers will send an HTTP POST to a URL you specify. This HTTP POST will contain the relevant data from the user action in JSON format. It will also have headers
X-Patreon-Event: <trigger>
X-Patreon-Signature: <message signature>
where the message signature is the JSON POST body HMAC signed (with MD5) with your client_secret

This is my code:

<?php
logData("asd");
$headers = getallheaders();
$X_Patreon_Event = $headers['X-Patreon-Event'];
$X_Patreon_Signature = $headers['X-Patreon-Signature'];
logMusic(json_decode($X_Patreon_Event));
logMusic(json_decode($X_Patreon_Signature));
function logData($str){
    $url = '/var/www/websitelog.txt';
    $current = "$str\n";
    file_put_contents($url,$current,FILE_APPEND | LOCK_EX);
}
Matthias Winkelmann
  • 15,870
  • 7
  • 64
  • 76
letsgo00
  • 127
  • 1
  • 2
  • 12

3 Answers3

3

getallheaders (since PHP 5.4.0) will return all headers as an associative array...

$headers = getallheaders();

...that you'll be then able to inspect to fetch the desired headers values

$X_Patreon_Event = $headers['X-Patreon-Event'];
$X_Patreon_Signature = $headers['X-Patreon-Signature'];

Side note: getallheaders() function may not be available (for example if your web server is nginx). In that case you can always re-implement the function with a little piece of code: Get the http headers from current request in PHP

Community
  • 1
  • 1
Paolo
  • 15,233
  • 27
  • 70
  • 91
  • 1
    I inspected the javascrip console and it says this error: `POST https://api.patreon.com/oauth2/webhooks/32/test?json-api-version=1.0 send @ jquery.min.js:2v.extend.ajax @ jquery.min.js:2(anonymous function) @ webhooks:714v.event.dispatch @ jquery.min.js:2o.handle.u @ jquery.min.js:2 webhooks:1 XMLHttpRequest cannot load https://api.patreon.com/oauth2/webhooks/32/test?json-api-version=1.0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.patreon.com' is therefore not allowed access. The response had HTTP status code 500.` – letsgo00 Feb 28 '16 at 21:07
  • this is because you do not send `Access-Control-Allow-Origin` header **in the AJAX request**. This has nothing to do with this question. – Paolo Feb 28 '16 at 21:07
  • The problem is that it does not send me to the page so I cannot echo it out or when I try to log it into a file nothing happens – letsgo00 Feb 28 '16 at 21:14
  • You wrote *My question is how to read header information with php received from other site* - if your problem is different then it deserves a different question. Isolate the problem, post the relevant part of your code and ask... – Paolo Feb 28 '16 at 21:18
2


I have a fully working webhooks page using php and mysqli hope this helps
NOTE** you need php 5.6 > for this to work
mysql DB tables required for my implementation

/**

-- Table structure for table patrons

CREATE TABLE IF NOT EXISTS patrons (
patron_key bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'key to row',
patron_id tinytext NOT NULL COMMENT 'patron id',
patron_fullname tinytext NOT NULL COMMENT 'fullname',
patron_firstname tinytext NOT NULL,
patron_lastname tinytext NOT NULL,
patron_email tinytext NOT NULL,
patron_image_url tinytext NOT NULL,
patron_pledge bigint(20) NOT NULL,
patron_list tinyint(4) NOT NULL COMMENT 'include in patrons honour list',
patron_decline tinytext,
PRIMARY KEY (patron_key)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

-- -- Table structure for table notifications

CREATE TABLE IF NOT EXISTS notifications (
notification_id bigint(20) NOT NULL AUTO_INCREMENT,
notification_type tinytext NOT NULL,
notification text NOT NULL,
notification_action int(11) NOT NULL,
notification_date tinytext NOT NULL,
notification_archived tinytext NOT NULL,
PRIMARY KEY (notification_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1401 ;

*/

$secret_webhook_id = "your-secret-key-here";

/** get the headers */
$headers = getallheaders();
$X_Patreon_Event = $headers['X-Patreon-Event'];
$X_Patreon_Signature = $headers['X-Patreon-Signature'];

/** get the json body */
$body = @file_get_contents("php://input");

/** get json body as array */
$patron_data = json_decode($body, true);

/** compute an md5 hash using the body and your secret key */
$signature = hash_hmac('md5', $body, $secret_webhook_id);

/** Timing attack safe string comparison */
if (hash_equals ($X_Patreon_Signature, $signature)){

/** get the data from the json array - look for errors*/
if (isset($patron_data['included']) && isset($patron_data['data'])) {
$data             = $patron_data['data'];
$declined         = $data['attributes']['declined_since'];

/** stored as a string*/
$declined         = is_null($declined) ? "":$declined;

$included         = $patron_data['included'];
$patron_id        = $included[0]['id'];
$patron_full_name = $included[0]['attributes']['full_name'];
$patron_firstname = $included[0]['attributes']['first_name'];
$patron_lastname  = $included[0]['attributes']['last_name'];
$patron_email     = $included[0]['attributes']['email'];
$patron_image_url = $included[0]['attributes']['image_url'];
$pledge           = $included[1]['attributes']['amount_cents'];

/** select event for db insert/update/delete*/
switch ($X_Patreon_Event){
    case "pledges:create":
        $sql = "INSERT INTO patrons SET patron_id  = ?, patron_fullname = ?, patron_firstname = ?, patron_lastname = ?, patron_email = ?, patron_image_url = ?, patron_pledge = ?, patron_list = 1, patron_decline = ?";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param("ssssssis", $patron_id, $patron_full_name, $patron_firstname, $patron_lastname, $patron_email, $patron_image_url, $pledge, $declined);
        if (!$stmt->execute()) {
            /** your_error_routine(__LINE__, __FILE__, $sql, $stmt->error); */
        }
        break;
    case "pledges:update":
        $sql = "UPDATE patrons SET patron_fullname = ?, patron_firstname = ?, patron_lastname = ?, patron_email = ?, patron_image_url = ?, patron_pledge = ?, patron_decline = ? WHERE patron_id = ?";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param("sssssiss", $patron_full_name, $patron_firstname, $patron_lastname, $patron_email, $patron_image_url, $pledge, $declined, $patron_id);
        if (!$stmt->execute()) {
            /** your_error_routine(__LINE__, __FILE__, $sql, $stmt->error); */
        }
        break;
    case "pledges:delete":
        $sql = "DELETE FROM patrons WHERE patron_id = ?";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param("s", $patron_id);
        if (!$stmt->execute()) {
             /** your_error_routine(__LINE__, __FILE__, $sql, $stmt->error); */
        }
        break;
}

/** now update your own admin notifications */
$notification = "Patreon Webhook update for: $patron_full_name - X_Patreon_Event: $X_Patreon_Event";
$sql = "INSERT INTO notifications SET notification_type = 'Patreon', notification = ?, notification_date = ".time();
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $notification);
if (!$stmt->execute()) {
    /** your_error_routine(__LINE__, __FILE__, $sql, $stmt->error); */
}

}

Steve Whitby
  • 403
  • 4
  • 8
1

In your script write:

var_dump($_SERVER);

and you will see returning variables. You can then access them like an array.

As was answered here, getallheaders() is what you are looking for.

And since its JSON, use json_decode() on those vars, read up on manual about json_decode/encode.

Muhammed
  • 1,592
  • 1
  • 10
  • 18