Webhook Signature Mismatch for payment.created & payment.updated webhooks

I am only seeing this error in my production account (not either of my sandbox accounts). When I try to validate the payment.created and payment.updated events, the hash I produce on my end does not match the signature received from the headers.

Note, I did see some successful calls in my logs for these two endpoints, however it only seems to fail when the data itself has multiple nested objects ( Example: the data.object.payment object has deeply nested objects such as data.object.payment.card_details.card)

Additional information:

  • My app ID is sq0idp-NLJQVmndw8XyEYi27ygs-g
  • I’m receiving the webhooks via AWS SQS, which then gets processed by my NodeJS application. Not sure if this would cause any issues in itself, but I have not had any issues up to this point with it.

Do you have a specific payment_id that you experienced this with?

Here are a few, but I have many many more.

3HshJxoUP7unAV9Yt5KGkCVMuaB, TBsIwgByHtaOrOT9bS6G1rbAwaB, XlNYiXtcG3v97Fe4yMVWVpwVvaB

Is there a specific function you run when creating your signature? (Like sorting the attributes before hashing, etc.)

Want to provide an update and let you know that the team is looking into this.

Thank you, I appreciate you getting back to me!

Hey @Bryan-Square,

Is there any word on this? I just noticed the same behavior on payment.created/payment.updated webhooks in my staging environment (sandbox app ID sandbox-sq0idb-sOKs0XyV7WiLz6_kQdSKug). However for some reason or another everything seems to be validating correctly in my dev environment (sandbox app ID sandbox-sq0idb-kK3X_6CjO00oyDWtTS3a3A). All three environments are currently utilizing version 2021-08-18 of the Square API

Hey @Bryan-Square ,

Is there any update on this?

They are still looking into this. :slightly_smiling_face:

Thanks for your patience on this. The team believe that the problem is key ordering and recommends that apps use the raw bytes from the request rather than converting the object representation in your language back to bytes for signature validation. :slightly_smiling_face:

Not sure it helps,
But I found a solution for a similar problem:

For those who just ran into this problem like I did, I have an observation to share and a recommendation to Square. Hopefully these will save others from spending 3+ hours on troubleshooting this like I did:

  1. To calculate an HMAC-SHA256 hash that matches that of Square, the JSON string read from the HTTP request body must have no spaces or carriage returns between the elements. In other words, the input to the HMAC function needs to be one long line of string with no space (except if there is a space in any JSON value, then you’d keep it.)

  2. Log entries provided by Square via this Web page:
    developer . squareup . com /apps/{your_app_id}/webhooks/events

is VERY misleading.

  • Some of the attributes Square sent to my Webhook does not show up in this Web log. For example, I tested the payment.updated webhook. The actual calls includes a created_at attribute, but the log shown on the Web doesn’t have it.
  • The order of attributes shown in the Web log and in the actual call are different. I understand that order of JSON attributes are not guaranteed. But when it comes to hashing, the order matters. So when I tried to manually calculate the HMAC using the payload from the Web log entries, it does not work. I recommend that Square shows the log on the Web that matches the actual payload sent, or warn people on that page itself that they can’t use it to troubleshoot their HMAC problem.

Hope this helps.

1 Like