shopify-webhooks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Shopify 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/create
,
app/uninstalled
).
Webhooks是与Shopify数据保持同步的首选方式。它们允许你的应用在店铺发生事件时(例如
orders/create
app/uninstalled
)接收实时通知。

1. Verification (CRITICAL)

1. 验证(至关重要)

ALL webhook requests must be verified to ensure they came from Shopify.
所有webhook请求都必须经过验证,确保它们确实来自Shopify。

HMAC Verification

HMAC验证

Shopify includes an
X-Shopify-Hmac-Sha256
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.
[!IMPORTANT] Always use the raw request body (Buffer) for verification. Parsed JSON bodies may have subtle differences that cause verification to fail.
Shopify在每个webhook请求中都包含
X-Shopify-Hmac-Sha256
请求头。这是请求体的base64编码HMAC-SHA256摘要,使用你的**客户端密钥(API Secret Key)**作为签名密钥。
[!重要提示] 始终使用**原始请求体(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
@shopify/shopify-app-remix
, verification is handled automatically by the
authenticate.webhook
helper.
typescript
/* 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-remix
authenticate.webhook
助手会自动处理验证逻辑。
typescript
/* 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
shopify.app.toml
. 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.,
app/uninstalled
).
toml
[webhooks]
api_version = "2025-10"

  [[webhooks.subscriptions]]
  topics = [ "app/uninstalled", "orders/create" ]
  uri = "/webhooks"
这些在
shopify.app.toml
中配置,应用部署时会自动注册,更易于管理。最适合通用的应用相关主题(例如
app/uninstalled
)。
toml
[webhooks]
api_version = "2025-10"

  [[webhooks.subscriptions]]
  topics = [ "app/uninstalled", "orders/create" ]
  uri = "/webhooks"

Shop-specific Webhooks (Advanced)

店铺级Webhooks(高级)

Use
webhookSubscriptionCreate
via the Admin API. Best for:
  • 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
shopify.app.toml
or via API.
  • customers/data_request
    : Request to export customer data.
  • customers/redact
    : Request to delete customer data.
  • shop/redact
    : Request to delete shop data (48 hours after uninstall).
[!WARNING] Failure to handle these can result in app removal.
公开应用必须实现特定的webhooks以符合隐私法规要求。这些需要在**合作伙伴后台(App > Configuration > Privacy compliance)**中配置,不能在
shopify.app.toml
或通过API配置。
  • customers/data_request
    :导出客户数据的请求
  • customers/redact
    :删除客户数据的请求
  • shop/redact
    :删除店铺数据的请求(应用卸载48小时后触发)
[!警告] 未处理这些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
    200 OK
    immediately (within 5 seconds). Perform long-running tasks asynchronously (e.g., using a background queue).
  • App Uninstalled: ALWAYS handle
    app/uninstalled
    to clean up shop data and cancel subscriptions. This webhook acts as the "offboarding" signal.
  • App Uninstalled: ALWAYS handle
    app/uninstalled
    to clean up shop data and cancel subscriptions. This webhook acts as the "offboarding" signal.
  • 幂等性:Webhooks可能被多次投递,确保你的处理逻辑是幂等的(例如在执行操作前检查订单是否已经处理过)。
  • 响应时间立即返回
    200 OK
    响应(5秒内),长时间运行的任务请异步处理(例如使用后台队列)。
  • 应用卸载事件:始终处理
    app/uninstalled
    事件来清理店铺数据、取消订阅。该webhook是应用的「卸载」信号。
  • 应用卸载事件:始终处理
    app/uninstalled
    事件来清理店铺数据、取消订阅。该webhook是应用的「卸载」信号。

Common Topics

常见主题

  • APP_UNINSTALLED
    : App removed. Cleanup required.
  • ORDERS_CREATE
    : New order placed.
  • ORDERS_PAID
    : Order payment status changed to paid.
  • PRODUCTS_UPDATE
    : Product details changed.
  • APP_UNINSTALLED
    :应用被移除,需要清理数据
  • ORDERS_CREATE
    :新订单提交
  • ORDERS_PAID
    :订单支付状态变更为已支付
  • PRODUCTS_UPDATE
    :产品详情变更