I can't find any information on what algorithm to use to decode WooCommerce webhook field X-Wc-Webhook-Signature in PHP. Does anyone know how to decode it?
Thanks!
I can't find any information on what algorithm to use to decode WooCommerce webhook field X-Wc-Webhook-Signature in PHP. Does anyone know how to decode it?
Thanks!
Expanding on the current answers, this is the PHP code snippet you need:
$sig = base64_encode(hash_hmac('sha256', $request_body, $secret, true));
Where $secret is your secret, $request_body is the request body, which can be fetched with file_get_contents('php://input');
The $sig value should then be equal to the X-Wc-Webhook-Signature request header.
To expand on the laravel solution this is how I created middleware to validate the incoming webhook.
Create middleware. The application that I am using keeps the WooCommerce consumer key and secret in a table assigned to a given store.
class ValidateWebhook
{
/**
* Validate that the incoming request has been signed by the correct consumer key for the supplied store id
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$signature = $request->header('X-WC-Webhook-Signature');
if (empty($signature)) {
return response(['Invalid key'], 401);
}
$store_id = $request['store'];
$consumer_key = ConsumerKeys::fetchConsumerSecretByStoreId($store_id);
$payload = $request->getContent();
$calculated_hmac = base64_encode(hash_hmac('sha256', $payload, $consumer_key, true));
if ($signature != $calculated_hmac) {
return response(['Invalid key'], 401);
}
return $next($request);
}
}
Register the middleware in Kernel.php
'webhook' => \App\Http\Middleware\ValidateWebhook::class,
Protect the webhook route with the middleware
Route::post('webhook', 'PrintController@webhook')->middleware('webhook');
Here is my solution for this question. You need to generate a sha256 hash for the content that was sent [payload] and encode it in base64. Then just compare the generated hash with the received one.
$secret = 'your-secret-here';
$payload = file_get_contents('php://input');
$receivedHeaders = apache_request_headers();
$receivedHash = $receivedHeaders['X-WC-Webhook-Signature'];
$generatedHash = base64_encode(hash_hmac('sha256', $payload, $secret, true));
if($receivedHash === $generatedHash):
//Verified, continue your code
else:
//exit
endif;
Here's my laravel / lumen function to verify the webhook request, hope it helps someone!
private function verifyWebhook(Request $request) {
$signature = $request->header('x-wc-webhook-signature');
$payload = $request->getContent();
$calculated_hmac = base64_encode(hash_hmac('sha256', $payload, 'WOOCOMMERCE_KEY', true));
if($signature != $calculated_hmac) {
abort(403);
}
return true;
}