Webhook security not consistent

Hello,

We have recently found a problem where one of our customers that uses the Square App to complete a transaction does not have it reflected back onto our site. We have the payments.update event set up to listen for updates and then reflect the payment back into our system. This is set up along with a few other hooks.

This customer is able to use gift cards in the Square App and have the transaction be picked up by the hook, but when using credit cards this does not appear to be the case. Looking at our logs the hook is stopped when comparing the ‘x-square-hmacsha256-signature’ value for security. Other customers that are using credit cards are having no problem it seems.

Are there any possible tips as to what could be the difference in this case? I know some fields are omitted for the gift card. My only thought was to the ‘&’ in the customer’s statement_description but I am unsure if that would really be a problem.

Thanks

Is there any whitespace that could be causing the issue? :slightly_smiling_face:

Hi Bryan,

There is no white space at the beginning or ending of the string, nor is there any in the structured part of the JSON. There is white space in the statement_description and application_name of the card details though. I have tried removing this but I still do not get the correct hash and it actually causes my other hashes for known working requests to become incorrect.

This is the PHP code we use to make the hash and compare.

$jsonBody = json_encode($request->data, JSON_UNESCAPED_SLASHES);
$hash = hash_hmac('sha256', $url.$jsonBody, $key, true);
$hash = base64_encode($hash);

if($hash !== $request->header('x-square-hmacsha256-signature')){ 

We have also attempted the following instead of pulling from our frameworks request and using json_encode:

$handle = fopen('php://input', 'r');
while(!feof($handle)) {
    $body .= fread($handle, 1024);
}

This is directly from the Square example but it also does not work and actually causes our known working examples to fail as well.

A follow up to this post. We ended up making it work by using the below method. When testing it wouldn’t work, but we put it live as something to try and it seemed to fix the problem.

$handle = fopen('php://input', 'r');
while(!feof($handle)) {
    $body .= fread($handle, 1024);
}

Thanks for sharing your findings. :slightly_smiling_face: