DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 966,904 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Borhan Tipu
Borhan Tipu

Posted on • Updated on

Django Shopify Webhook HMAC Verify

In this article, I will show you how you can verify Shopify Webhook Hmac in a Django Application.

In Shopify:
Go to Settings > Notifications > Webhook

  1. Create a Webhook
  2. Add Webhook URL

Create Webhook
Create Webhook

You can use ngrok for development and testing purpose

SHOPIFY_WEBHOOK_SIGNED_KEY
Enter fullscreen mode Exit fullscreen mode

SHOPIFY_WEBHOOK_SIGNED_KEY
After adding the webhook URL you will find a Signed Key for webhook just below of the Webhook URL list.
In Django:

Add a variable in settings.py file

SHOPIFY_WEBHOOK_SIGNED_KEY = env.str('SHOPIFY_WEBHOOK_SIGNED_KEY', '')
Enter fullscreen mode Exit fullscreen mode

Then in your views.py file,

I used django-rest-framework views, response, and status

from django.views.decorators.csrf import csrf_exempt  
from rest_framework import status  
from rest_framework.decorators import api_view  
from rest_framework import status  
from rest_framework.response import Response
import hmac  
import hashlib  
import base64

def computed_hmac(secret, body):  
    hash_code = hmac.new(secret.encode('utf-8'), body, hashlib.sha256)  
    return base64.b64encode(hash_code.digest()).decode()

def verify_hmac(secret, body, shopify_hmac):  
    return computed_hmac(secret, body) == shopify_hmac

@csrf_exempt
@api_view(['POST'])  
def api_view_webhook(request):
    # get hmac from shopify webhook request  
    shopify_hmac = request.headers.get('X-Shopify-Hmac-Sha256')  
    if verify_hmac(settings.SHOPIFY_WEBHOOK_SIGNED_KEY, request.body, shopify_hmac):  
        print('valid')  
        return Response(status=status.HTTP_200_OK) else:  
    else:
        print('invalid')  
        return Response(status=status.HTTP_400_BAD_REQUEST)
Enter fullscreen mode Exit fullscreen mode

In your urls.py file,

from .views import_ api_view_webhook
urlpatterns = [  
    path('webhook/', api_view_webhook, name='api_view_webhook'),  
]
Enter fullscreen mode Exit fullscreen mode

If verify_hmac is True then it will print β€œvalid” in terminal console otherwise it will print **β€œinvalid”.

**That’s it.

Thanks.

You can find this article in medium also

Top comments (10)

Collapse
 
shahrukhahmed profile image
Shahrukh Ahmed

Thank you for the tutorial. Where do you get the settings.SHOPIFY_WEBHOOK_SIGNED_KEY from? Can I use the Shopify API Secret Key?

Collapse
 
tipu profile image
Borhan Tipu Author

After adding the webhook URL you will find a Signed Key for webhook just below of the Webhook URL list

Collapse
 
shahrukhahmed profile image
Shahrukh Ahmed

Ah, so for public apps you have to add the API secret key. :)

Thread Thread
 
tipu profile image
Borhan Tipu Author • Edited on

Check this on Medium. I posted the same thing. May be here something missing
medium.com/@BorhanTipu/django-shop...

Thread Thread
 
shahrukhahmed profile image
Shahrukh Ahmed

Thanks man. Got it working in the end with the APP API key. The problem was with encoding. Your code really helped. Thank you very much.

Thread Thread
 
tipu profile image
Borhan Tipu Author

You are welcome. I also faced this issue. After figure it out I published this article so that other can get helps from it.

Thread Thread
 
shahrukhahmed profile image
Shahrukh Ahmed

Good job. Keep writing more. :)

Collapse
 
koblintz profile image
koblintz

Hi - vv helpful, but couple of minor typos in your code

should be a 'def' in front of 'computed_hmac'

in the 'verify_hmac' def, the second line should be
return computed_hmac(secret, body) == shopify_hmac

(you have 'get_hmac')

Collapse
 
tipu profile image
Borhan Tipu Author

Thanks. I will update it.

Collapse
 
bennyychan profile image
Benny Chan

Great! Work like a charm

Update Your DEV Experience Level:

Settings

Go to your customization settings to nudge your home feed to show content more relevant to your developer experience level. πŸ›