How to setup mandatory webhooks for a public Shopify app in your Django application

When you want to publish a public Shopify app, you need to setup three mandatory webhooks. shopify.dev provides good documentation and a few code examples, which you’ll all find on this page.

What kind of logic to write within the # Process webhook payload comments will depend on your approach and project structure. In my case I retrieve a “ShopifyConnect” model based on the “shop_id” from the retrieved body and send an email to the shop owner aka. my user, with the needed information. You can read more about the purpose per view on this page.

For local test environments I prefer using Ngrok, which is very easy to use following their documentation.

views.py

from django.views.decorators.csrf import csrf_exempt
import hmac  
import hashlib  
import base64

API_SECRET_KEY = 'shpss_xxx'

def _verify_webhook(data, hmac_header):
    digest = hmac.new(API_SECRET_KEY.encode('utf-8'), data, digestmod=hashlib.sha256).digest()
    computed_hmac = base64.b64encode(digest)

    return hmac.compare_digest(computed_hmac, hmac_header.encode('utf-8'))

@csrf_exempt
def customer_data_request(request):
    verified = _verify_webhook(request.body, request.headers['X-Shopify-Hmac-SHA256'])
    if not verified:
        return HttpResponse('Unauthorized', status=401)
    # Process webhook payload
    # ...
    return HttpResponse('Authorized', status=200)

@csrf_exempt
def customer_data_erasure(request):
    verified = _verify_webhook(request.body, request.headers['X-Shopify-Hmac-SHA256'])
    if not verified:
        return HttpResponse('Unauthorized', status=401)
    # Process webhook payload
    # ...
    return HttpResponse('Authorized', status=200)

@csrf_exempt
def shop_data_erasure(request):	
    verified = _verify_webhook(request.body, request.headers['X-Shopify-Hmac-SHA256'])
    if not verified:
        return HttpResponse('Unauthorized', status=401)
    # Process webhook payload
    # ...
    return HttpResponse('Authorized', status=200)

urls.py

from django.urls import repath
from . import views

urlpatterns = [
    re_path(r'^webhook/customers/data-request$', views.customer_data_request, name='customer_data_request'),
    re_path(r'^webhook/customers/redact$', views.customer_data_erasure, name='customer_data_erasure'),
    re_path(r'^webhook/shop/redact$', views.shop_data_erasure, name='shop_data_erasure')
]

Leave a comment

Your email address will not be published. Required fields are marked *