Hi,
I have been looking for documentation on how to verify webhooks for public apps and I am unable to find any. From, what I have gathered, private apps use a WEBHOOK_SIGNED_KEY available at the store admin level. I thought using API Key / API Secret could be an alternative for public apps, but that doesn't seem to be the case. The below code is what I have tried up till now. Thank you.
def verify_hmac(secret, body, shopify_hmac):
hash_code = hmac.new(secret.encode('utf-8'), body, hashlib.sha256)
computed_hmac = base64.b64encode(hash_code.digest()).decode()
return computed_hmac == shopify_hmac
@csrf_exempt
def save_webook_payload(request):
if request.method == 'POST':
shopify_hmac = request.headers.get('X-Shopify-Hmac-Sha256')
if verify_hmac(SHOPIFY_API_SECRET, request.body, shopify_hmac):
return JsonResponse( { 'data': 'Payload Recieved'}, safe = False )
else:
raise Http404("No such Page")
raise Http404("No such Page")
Solved! Go to the solution
This is an accepted solution.
If you refer to this link, there's a Ruby version of the routine to validate the HMAC signature sent with the webhook request --> https://shopify.dev/tutorials/manage-webhooks. You should be able to use that as a basis for your Python code. Hope this helps!
Here is sample code in C# that compares the provided HMAC against the calculated one. Works like a charm in production for our app proxy deployment.
var query = "path_prefix=" + path_prefix
+ "shop=" + shop
+ "timestamp=" + timestamp;
var secret_key = "MY_SECRET_KEY";
var ascii = new ASCIIEncoding();
var keyBytes = ascii.GetBytes(secret_key);
using (var hmac = new HMACSHA256(keyBytes))
{
var queryBytes = ascii.GetBytes(query);
var hashedQuery = hmac.ComputeHash(queryBytes);
var computedHash = ToHexString(hashedQuery);
if (computedHash == signature)
{
// Hooray!!!
}
else
{
// Boo!!!
}
}
private static string ToHexString(byte[] array)
{
StringBuilder hex = new StringBuilder(array.Length * 2);
foreach (byte b in array)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
Sorry, as my post was for verifying the app proxy calls, not the webhooks. This is directly from the Shopify GitHub example page. Ruby code...
def validate_hmac(hmac,request)
h = request.params.reject{|k,_| k == 'hmac' || k == 'signature'}
query = URI.escape(h.sort.collect{|k,v| "#{k}=#{v}"}.join('&'))
digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), API_SECRET, query)
unless (hmac == digest)
return [403, "Authentication failed. Digest provided was: #{digest}"]
end
end
def verify_webhook(hmac, data)
digest = OpenSSL::Digest.new('sha256')
calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, API_SECRET, data)).strip
hmac == calculated_hmac
end
User | Count |
---|---|
12 | |
12 | |
10 | |
7 | |
6 |