<?php
namespace Square\Utils;
use Exception;
/**
* Utility to help with Square Webhooks
*/
class WebhooksHelper {
/**
* Verifies and validates an event notification.
* See the documentation for more details.
*
* @param string $requestBody The JSON body of the request.
* @param string $signatureHeader The value for the `x-square-hmacsha256-signature` header.
* @param string $signatureKey The signature key from the Square Developer portal for the webhook subscription.
* @param string $notificationUrl The notification endpoint URL as defined in the Square Developer portal for the webhook subscription.
* @return bool `true` if the signature is valid, indicating that the event can be trusted as it came from Square. `false` if the signature validation fails, indicating that the event did not come from Square, so it may be malicious and should be discarded.
* @throws Exception If the signatureKey or notificationUrl is null or empty.
*/
public static function isValidWebhookEventSignature(
string $requestBody,
string $signatureHeader,
string $signatureKey,
string $notificationUrl
): bool {
if ($requestBody === null) {
return false;
}
if ($signatureKey === null || strlen($signatureKey) === 0) {
throw new Exception('signatureKey is null or empty');
}
if ($notificationUrl === null || strlen($notificationUrl) === 0) {
throw new Exception('notificationUrl is null or empty');
}
// Perform UTF-8 encoding to bytes
$payload = $notificationUrl . $requestBody;
$payloadBytes = mb_convert_encoding($payload, 'UTF-8');
$signatureKeyBytes = mb_convert_encoding($signatureKey, 'UTF-8');
// Compute the hash value
$hash = hash_hmac('sha256', $payloadBytes, $signatureKeyBytes, true);
// Compare the computed hash vs the value in the signature header
$hashBase64 = base64_encode($hash);
return $hashBase64 === $signatureHeader;
}
}