Verify Webhook : PHP Example

1,687 views
Skip to first unread message

tarwin

unread,
Feb 13, 2012, 8:27:29 PM2/13/12
to shopify-api
Hi,

I've been trying to get the webhook verification working properly in
PHP. The example given @ http://wiki.shopify.com/Verifying_Webhooks is
in Ruby, and it took me a little white to decipher exactly what it was
doing, but did manage to (I think).

My PHP version look like this:

--------------------------------------------------

$headers = apache_request_headers();
$action = $headers['x-shopify-topic'];

if ($action == 'app/uninstalled'){
$hmac = $headers['x-shopify-hmac-sha256'];
if ($hmac == computeSignature()) {
echo "ok";
}else{
echo "error";
}
}

function computeSignature(){
return hash_hmac('sha256', file_get_contents('php://input'),
SHOPIFY_SECRET);
}

--------------------------------------------------

I'm currently not able to get this to verify. I'm thinking of just
adding my own hash (with salt) when I add webhooks so I can check it
my own way.

But would love to have it working the "correct" way - also would be
nice to have a PHP example on the wiki too.

Thanks,

Dave

unread,
Feb 13, 2012, 9:01:23 PM2/13/12
to shopify-api
You can't add your own security to a Webhook. The contents of the
Webhook are created by Shopify, not you. Glueing on something
arbitrary to your GET is no extra security.

Best that you just figure out the part about computing the hash
properly. PHP most certainly has at least one, but more likely ten to
a hundred utility methods to mimic what the Ruby example does.

Ben Dunlap

unread,
Feb 14, 2012, 10:42:25 AM2/14/12
to shopify-api
> But would love to have it working the "correct" way - also would be
> nice to have a PHP example on the wiki too.

The PHP manual says hash_hmac() returns a "hexit" string if you leave
off the fourth argument, but you want a base64-encoded string. Try
changing the line in your computeSignature() function to this:

return base64_encode(hash_hmac('sha256', file_get_contents('php://
input'), SHOPIFY_SECRET, true));

Note the fourth argument to hash_hmac() -- this will make it return
raw binary data, which will then be fed to base64_encode().

Also I'm not sure if this line will work because your index is all-
lowercase:

$hmac = $headers['x-shopify-hmac-sha256'];

I think the indexes in $headers are going to be capitalized/uppercase/
lowercase exactly as Apache provides them. It might be easier and a
little more portable to use $_SERVER['X_SHOPIFY_HMAC_SHA256'].

Also a bit more logic there will help narrow down the failure point;
e.g.:

if (empty($_SERVER['X_SHOPIFY_HMAC_SHA256'])) {
die("header 'x-shopify-hmac-sha256' is blank or non-existent\n");
}

Ben

tarwin

unread,
Feb 14, 2012, 9:26:14 PM2/14/12
to shopify-api
@Ben




Thanks, but currently my setup was too complex to keep testing to see
if I could get it working the "correct" way, but thanks for the hint.
I'll post an example when I get it working in pure PHP..




@Dave




Adding something to the GET string does add security as long as it's
something secret that I can link to the call. For example, a salted
MD5 of the shop URL that is sent by Shopify. This could be either
salted by an arbitery secret string, or by the Shopify secret itself,
which I'm guessing should then be as secure as anything else ? That
is, unless someone manages to steal the URL that I sent as my hook,
which I don't get how this would happen.




Thanks,

Sandeep Shetty

unread,
Feb 15, 2012, 3:38:50 PM2/15/12
to shopi...@googlegroups.com
Hey Tarwin,

The changes @Ben suggested should work. Here is what I use:
https://gist.github.com/1838803

--
Sandeep Shetty
Founder, Simpthings
http://simpthings.com/
http://sandeep.shetty.in/p/about.html

tarwin

unread,
Feb 15, 2012, 6:17:45 PM2/15/12
to shopify-api
Thanks heaps Sandeep. Good to have this code on the list as well !
Reply all
Reply to author
Forward
0 new messages