Have your say in Community Polls: What was/is your greatest motivation to start your own business?
Our Partner & Developer boards on the community are moving to a brand new home: the .dev community forums! While you can still access past discussions here, for all your future app and storefront building questions, head over to the new forums.

Re: Webhook Validation: Python/Flask working example? HMAC.

Solved

Webhook Validation: Python/Flask working example? HMAC.

lowercase00
Shopify Partner
1 0 0

Hey all.

I've trying to get the webhook validation up and running for a while with no success.

I've seen the Ruby example, and was wondering if there's a Python example to validade the webhook sent to a Flask app.

Thanks a lot.

Accepted Solution (1)

dmulter
Shopify Partner
4 1 1

This is an accepted solution.

Take a look at Verifying webhooks section of the Using webhooks article, and click the Python button.

View solution in original post

Replies 9 (9)

dmulter
Shopify Partner
4 1 1

This is an accepted solution.

Take a look at Verifying webhooks section of the Using webhooks article, and click the Python button.

davidkong0987
Tourist
3 0 2
digest = hmac.new(SECRET.encode('utf-8'), data, hashlib.sha256).digest()

works for me instead of what's there 

JUNIORCO
Tourist
6 0 0

@davidkong0987 

Do you mind sharing the rest of your code? What I have so far is:

 

def verify_webhook(data, hmac_header):    
    digest = hmac.new(SECRET.encode('utf-8'), data, hashlib.sha256).digest()
    genHmac = base64.b64encode(digest)

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

@app.route('/', methods=['POST'])
def main(request):
    print('Received Webhook...')

    data = request.get_data()
    hmac_header = request.headers.get('X-Shopify-Hmac-SHA256')
    verified = verify_webhook(data, hmac_header)
    
    if not verified:
        # do stuff...
        return 'Integrity of request compromised...', 401
    
    # do stuff...
    print('Verified request...')

 

 But it isn't working! I have no idea why and the docs don't help either.

davidkong
Tourist
5 0 7
import hmac
import hashlib
import base64
from flask import Flask

app = Flask(__name__)

SECRET = ''



def verify_webhook(data, hmac_header):
    digest = hmac.new(SECRET.encode('utf-8'), data, hashlib.sha256).digest()
    computed_hmac = base64.b64encode(digest)
    return hmac.compare_digest(computed_hmac, hmac_header.encode('utf-8'))

@app.route('/productCreation', methods=['POST'])
def productCreation():
    data = request.data
    verified = verify_webhook(data, request.headers.get('X-Shopify-Hmac-SHA256'))
JUNIORCO
Tourist
6 0 0

@davidkongthank you so much!!!

TigersAndTacos
Tourist
6 0 4

You can also checkout the guide in this post which also includes a link to a repo that has a fully functioning webhook handlers writter in Python + Flask

Fredrik — Creator of bugs since 1999
KevinLopezBC
Shopify Partner
8 0 1

import hmac

import hashlib

import base64

from fastapi import FastAPI, Request, HTTPException

from fastapi.responses import Response

import os

 

load_dotenv()

 

app = FastAPI()

 

SHOPIFY_SECRET = os.getenv('SHOPIFY_SECRET')

 

def verify_webhook(raw_data, hmac_header, secret):

    digest = hmac.new(secret.encode('utf-8'), raw_data, digestmod=hashlib.sha256).digest()

    computed_hmac = base64.b64encode(digest).decode()

 

    print(f"SECRET: {secret}")

    print(f"RAW DATA: {raw_data}")

    print(f"RAW DATA (decoded): {raw_data.decode('utf-8')}")

    print(f"DIGEST (binary): {digest}")

    print(f"DIGEST (hex): {digest.hex()}")

    print(f"COMPUTED HMAC: {computed_hmac}")

    print(f"RECEIVED HMAC: {hmac_header}")

 

    return hmac.compare_digest(computed_hmac, hmac_header)

 

@app.post('/webhook/customer_data_request')

async def customer_data_request_webhook(request: Request):

    try:

        raw_data = await request.body()

        headers = dict(request.headers)

        print('HEADERS:', headers)

        print('RAW DATA:', raw_data)

        hmac_header = headers.get('X-Shopify-Hmac-SHA256')

        if not hmac_header:

            raise HTTPException(status_code=400, detail="Missing HMAC header")

        verified = verify_webhook(raw_data, hmac_header, SHOPIFY_SECRET)

        if not verified:

            print("Computed HMAC does not match the provided HMAC.")

            raise HTTPException(status_code=401, detail="HMAC verification failed")

 

        print("HMAC verification successful.")

        return Response(status_code=200)

 

    except Exception as e:

        print("Error processing customer data request webhook:")

        print(e)

        return Response(status_code=500, content=str(e))

 

 

 

I’m building a Shopify public app and I’m having trouble with the HMAC verification process. Despite using the Shopify Secret from the Dashboard of my app at partners.shopify.com, I can’t get the computed HMAC and the received HMAC to match. This always results in a failed verification.

I’ve tried various combinations, but nothing seems to work—they never match. There might be something I’m missing. I hope someone here has a solution.

maik
Shopify Partner
1 0 0

Hey @KevinLopezBC , did you find a solution? I'm stuck with the same. I can't get them to match in my orders/create webhook.

In the post mentioned above, I've seen that the author is putting a "shpss" and underscore in front of the secret, but this also didn't fix it for me.

KevinLopezBC
Shopify Partner
8 0 1

Hey there,

I didn’t find any solution, likely due to a conflict with middleware adding unwanted elements to the HTTP response.

Anyway, I had to set up a Flask server to handle this. It worked with the Shopify Flask code provided for the hmac verification, and my Flask server communicates back with my backend server. It worked on first try.

 

However, I didn’t find a direct solution, even after posting issues on FastAPI’s GitHub.