shopify-webhooks
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseShopify Webhooks Skill
Shopify Webhooks 技能
Webhooks are the preferred way to stay in sync with Shopify data. They allow your app to receive real-time notifications when events occur in a shop (e.g., , ).
orders/createapp/uninstalledWebhooks是与Shopify数据保持同步的首选方式。它们允许你的应用在店铺发生事件时(例如、)接收实时通知。
orders/createapp/uninstalled1. Verification (CRITICAL)
1. 验证(至关重要)
ALL webhook requests must be verified to ensure they came from Shopify.
所有webhook请求都必须经过验证,确保它们确实来自Shopify。
HMAC Verification
HMAC验证
Shopify includes an header in every webhook request. This is a base64-encoded HMAC-SHA256 digest of the request body, using your Client Secret (API Secret Key) as the signing key.
X-Shopify-Hmac-Sha256[!IMPORTANT] Always use the raw request body (Buffer) for verification. Parsed JSON bodies may have subtle differences that cause verification to fail.
Shopify在每个webhook请求中都包含请求头。这是请求体的base64编码HMAC-SHA256摘要,使用你的**客户端密钥(API Secret Key)**作为签名密钥。
X-Shopify-Hmac-Sha256[!重要提示] 始终使用**原始请求体(Buffer)**进行验证。解析后的JSON体可能存在细微差异,会导致验证失败。
Node.js Example (Generic)
Node.js 示例(通用)
javascript
const crypto = require('crypto');
function verifyWebhook(rawBody, hmacHeader, apiSecret) {
const digest = crypto
.createHmac('sha256', apiSecret)
.update(rawBody, 'utf8')
.digest('base64');
return crypto.timingSafeEqual(
Buffer.from(digest),
Buffer.from(hmacHeader)
);
}javascript
const crypto = require('crypto');
function verifyWebhook(rawBody, hmacHeader, apiSecret) {
const digest = crypto
.createHmac('sha256', apiSecret)
.update(rawBody, 'utf8')
.digest('base64');
return crypto.timingSafeEqual(
Buffer.from(digest),
Buffer.from(hmacHeader)
);
}Remix / Shopify App Template (Recommended)
Remix / Shopify 应用模板(推荐)
If using , verification is handled automatically by the helper.
@shopify/shopify-app-remixauthenticate.webhooktypescript
/* app/routes/webhooks.tsx */
import { authenticate } from "../shopify.server";
export const action = async ({ request }) => {
const { topic, shop, session, admin, payload } = await authenticate.webhook(request);
if (!admin) {
// The webhook request was not valid.
return new Response();
}
switch (topic) {
case "APP_UNINSTALLED":
if (session) {
await db.session.deleteMany({ where: { shop } });
}
break;
case "ORDERS_CREATE":
console.log(`Order created: ${payload.id}`);
break;
}
return new Response();
};如果使用,助手会自动处理验证逻辑。
@shopify/shopify-app-remixauthenticate.webhooktypescript
/* app/routes/webhooks.tsx */
import { authenticate } from "../shopify.server";
export const action = async ({ request }) => {
const { topic, shop, session, admin, payload } = await authenticate.webhook(request);
if (!admin) {
// Webhook请求无效
return new Response();
}
switch (topic) {
case "APP_UNINSTALLED":
if (session) {
await db.session.deleteMany({ where: { shop } });
}
break;
case "ORDERS_CREATE":
console.log(`Order created: ${payload.id}`);
break;
}
return new Response();
};2. Registration
2. 注册
App-specific Webhooks (Recommended)
应用级Webhooks(推荐)
These are configured in . They are automatically registered when the app is deployed and are easier to manage. Best for topics that apply to the app in general (e.g., ).
shopify.app.tomlapp/uninstalledtoml
[webhooks]
api_version = "2025-10"
[[webhooks.subscriptions]]
topics = [ "app/uninstalled", "orders/create" ]
uri = "/webhooks"这些在中配置,应用部署时会自动注册,更易于管理。最适合通用的应用相关主题(例如)。
shopify.app.tomlapp/uninstalledtoml
[webhooks]
api_version = "2025-10"
[[webhooks.subscriptions]]
topics = [ "app/uninstalled", "orders/create" ]
uri = "/webhooks"Shop-specific Webhooks (Advanced)
店铺级Webhooks(高级)
Use via the Admin API. Best for:
webhookSubscriptionCreate- Per-shop customization.
- Topics not supported by config.
- Dynamic runtime registration.
graphql
mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {
webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {
userErrors {
field
message
}
webhookSubscription {
id
}
}
}通过Admin API使用,适合以下场景:
webhookSubscriptionCreate- 按店铺自定义配置
- 配置文件不支持的主题
- 动态运行时注册
graphql
mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {
webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {
userErrors {
field
message
}
webhookSubscription {
id
}
}
}3. Mandatory Compliance (GDPR)
3. 强制合规要求(GDPR)
Public apps MUST implement specific webhooks to comply with privacy laws. These are configured in the Partner Dashboard (App > Configuration > Privacy compliance), NOT in or via API.
shopify.app.toml- : Request to export customer data.
customers/data_request - : Request to delete customer data.
customers/redact - : Request to delete shop data (48 hours after uninstall).
shop/redact
[!WARNING] Failure to handle these can result in app removal.
公开应用必须实现特定的webhooks以符合隐私法规要求。这些需要在**合作伙伴后台(App > Configuration > Privacy compliance)**中配置,不能在或通过API配置。
shopify.app.toml- :导出客户数据的请求
customers/data_request - :删除客户数据的请求
customers/redact - :删除店铺数据的请求(应用卸载48小时后触发)
shop/redact
[!警告] 未处理这些webhook可能导致应用被下架。
4. Best Practices
4. 最佳实践
- Idempotency: Webhooks can be delivered multiple times. Ensure your processing logic is idempotent (e.g., check if an order has already been processed before taking action).
- Response Time: Respond with a immediately (within 5 seconds). Perform long-running tasks asynchronously (e.g., using a background queue).
200 OK - App Uninstalled: ALWAYS handle to clean up shop data and cancel subscriptions. This webhook acts as the "offboarding" signal.
app/uninstalled - App Uninstalled: ALWAYS handle to clean up shop data and cancel subscriptions. This webhook acts as the "offboarding" signal.
app/uninstalled
- 幂等性:Webhooks可能被多次投递,确保你的处理逻辑是幂等的(例如在执行操作前检查订单是否已经处理过)。
- 响应时间:立即返回响应(5秒内),长时间运行的任务请异步处理(例如使用后台队列)。
200 OK - 应用卸载事件:始终处理事件来清理店铺数据、取消订阅。该webhook是应用的「卸载」信号。
app/uninstalled - 应用卸载事件:始终处理事件来清理店铺数据、取消订阅。该webhook是应用的「卸载」信号。
app/uninstalled
Common Topics
常见主题
- : App removed. Cleanup required.
APP_UNINSTALLED - : New order placed.
ORDERS_CREATE - : Order payment status changed to paid.
ORDERS_PAID - : Product details changed.
PRODUCTS_UPDATE
- :应用被移除,需要清理数据
APP_UNINSTALLED - :新订单提交
ORDERS_CREATE - :订单支付状态变更为已支付
ORDERS_PAID - :产品详情变更
PRODUCTS_UPDATE