如何在AWS Lambda(Node.js)+API Gateway中验证处理Shopify Webhook
Shopify Webhook验证(Lambda + API Gateway 代理集成)
核心问题解答
1. Webhook签名令牌的正确用法
你在Shopify后台创建的订单创建Webhook,使用的是Shopify提供的Webhook签名秘钥(Signing Secret),而非店铺的ACCESS_TOKEN或Headless应用的私有令牌。这个秘钥可在Shopify后台Webhook设置页面获取(创建时显示,也可重新生成)。
初始化shopifyApi时,无需传入accessToken,需将apiSecretKey配置为该签名秘钥,同时设置isPrivateApp: false(这是店铺后台创建的标准Webhook,不属于私有应用范畴)。
2. Lambda环境中获取验证所需参数
在API Gateway代理集成的Lambda中:
rawBody:从event.body获取,若event.isBase64Encoded为true,需用Buffer.from(event.body, 'base64').toString()解码。rawRequest:无需完整HTTP请求对象,传入包含请求头的对象{ headers: event.headers }即可。rawResponse:可传入空对象,验证过程不会实际依赖它发送响应,后续自行返回Lambda响应即可。
完整代码示例
import "@shopify/shopify-api/adapters/node"; import { shopifyApi } from "@shopify/shopify-api"; // 替换为你的店铺域名(不带https,例如your-store.myshopify.com) const SHOP_NAME = 'your-store.myshopify.com'; // 替换为Shopify Webhook设置中获取的签名秘钥 const WEBHOOK_SIGNING_SECRET = 'your-webhook-signing-secret'; const shopify = shopifyApi({ shopName: SHOP_NAME, apiSecretKey: WEBHOOK_SIGNING_SECRET, isPrivateApp: false, // 关键:这是店铺后台创建的标准Webhook,不是私有应用 }); exports.handler = async (event, context) => { try { // 处理请求体的base64编码情况 const rawBody = event.isBase64Encoded ? Buffer.from(event.body, 'base64').toString() : event.body; const validationResult = await shopify.webhooks.validate({ rawBody: rawBody, rawRequest: { headers: event.headers }, rawResponse: {}, // 空对象即可,验证过程不依赖它 }); if (!validationResult.isValid) { console.error('Webhook验证失败:', validationResult); return { statusCode: 401, body: JSON.stringify({ error: 'Invalid webhook signature' }) }; } // 验证通过,处理订单数据 const orderData = JSON.parse(rawBody); console.log('收到订单:', orderData.id); // 这里添加你的业务处理逻辑(如保存到数据库、触发其他流程) // 返回200给Shopify,否则Shopify会重试Webhook return { statusCode: 200, body: JSON.stringify({ success: true }) }; } catch (error) { console.error('Webhook处理出错:', error); return { statusCode: 500, body: JSON.stringify({ error: 'Internal server error' }) }; } };
注意事项
- 确保API Gateway完整传递请求头,尤其是
X-Shopify-Hmac-Sha256、X-Shopify-Topic等Shopify专属头,不要在网关中移除。 - Shopify要求Webhook端点在5秒内返回200响应,若处理逻辑耗时较长,建议异步处理(如发送到SQS队列,由其他Lambda后续处理),避免超时。
- 签名秘钥不要硬编码,建议用AWS Secrets Manager或Lambda环境变量存储。
内容的提问来源于stack exchange,提问作者slim.mckins
相关产品推荐
相关产品推荐

