Flask开发Shopify Webhooks接口时Hmac验证失败报错如何解决
问题原因
- 报错核心原因是对已经为
bytes类型的对象调用了encode()方法:encode()是字符串类型转为bytes类型的方法,bytes类型本身没有该方法,触发属性异常。 - 你贴出的示例代码中
verify_webhook函数直接传入request.data(Flask中该属性本身就是原始请求body的bytes类型)没有多余encode操作,说明你实际运行的代码和贴出的代码存在差异,实际代码在传入hmac.new的第二个参数时多加了.encode('utf-8')操作。 - 额外排查点:如果后续解决编码问题后仍出现验证失败,需确认是否在取
request.data前调用了request.get_json()、request.form等会预先解析请求body的方法,这类操作会修改原始body内容,导致HMAC计算结果不匹配。
解决方案
修正后的可运行完整代码如下:
import hmac import hashlib import base64 from flask import Flask, request app = Flask(__name__) # 替换为你Shopify后台对应Webhook的签名密钥 SECRET = "你的Shopify Webhook签名密钥" def verify_webhook(data: bytes, hmac_header: str) -> bool: 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(): # 优先取HMAC请求头,不存在直接返回401 hmac_header = request.headers.get('X-Shopify-Hmac-SHA256') if not hmac_header: return("Integrity error", 401) # 必须取原始未解析的request.data,不要提前调用get_json等方法 data = request.data verified = verify_webhook(data, hmac_header) if verified: # 验证通过后再处理业务逻辑 return ("Success", 200) return("Integrity error", 401) if __name__ == '__main__': app.run(debug=True)
- 操作步骤:
- 删除你实际代码中给消息参数额外加的
.encode('utf-8')代码,保持传入hmac.new的第二个参数为原始bytes类型的请求body - 确认
SECRET变量值和Shopify后台Webhook设置页的签名密钥完全一致,不要误用Shopify的API密钥 - 确保在获取
request.data前没有调用任何会解析请求body的方法,保证计算HMAC用的是原始请求数据
内容的提问来源于stack exchange,提问作者Deepak Kumar
相关产品推荐
相关产品推荐

