You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检查Webhook是否存在并避免重复创建?

解决Shopify重复注册Webhook的问题

核心思路

每次认证回调时先查询店铺已注册的Webhook列表,对比你需要的Webhook配置(topic+callbackUrl+deliveryMethod),仅注册不存在的Webhook,避免重复创建。

实现步骤

  1. 新增Webhook检查函数:通过Shopify Rest API获取已有的Webhook,筛选出缺失的目标Webhook
  2. 修改认证回调逻辑:在调用webhooks.register前先执行检查,只注册缺失的Webhook

修改后的完整代码

import { DeliveryMethod, shopify } from './your-shopify-import-path'; // 根据实际路径调整

const handleWebhookRequest = async (
  topic: string,
  shop: string,
  webhookRequestBody: string,
  webhookId: string,
  apiVersion: string,
) => {
  const sessionId = shopify.session.getOfflineId(shop);

  console.log('H');
  console.log(webhookId);
  console.log(sessionId);
  
  // Fetch the session from storage and process the webhook event
};

shopify.webhooks.addHandlers({
  PRODUCTS_CREATE: [
    {
      deliveryMethod: DeliveryMethod.Http,
      callbackUrl: '/webhooks',
      callback: async (topic, shop, body, webhookId) => {
        console.log('--- Product update ---');
        const payload = JSON.parse(body);
        console.log(payload);
        console.log('--- /Product update ---');
      },
    },
  ],
  PRODUCTS_UPDATE: [
    {
      deliveryMethod: DeliveryMethod.Http,
      callbackUrl: '/webhooks',
      callback: handleWebhookRequest,
    },
  ],
});

app.get('/auth', async (req: any, res: any) => {
  try {
    await shopify.auth.begin({
      shop: shopify.utils.sanitizeShop(req.query.shop, true),
      callbackPath: '/auth/callback',
      isOnline: false,
      rawRequest: req,
      rawResponse: res,
    });
  } catch(e) {
    console.log(e);
    res.send(e);
  }
});

// 新增:检查已存在的Webhook,返回缺失的目标Webhook
async function checkExistingWebhooks(session, desiredWebhooks) {
  const client = new shopify.clients.Rest({ 
    session, 
    apiVersion: process.env.SHOPIFY_API_VERSION // 确保配置了正确的API版本
  });
  const response = await client.get({ path: 'webhooks' });
  const existingWebhooks = response.body.webhooks || [];

  // 用topic+address作为唯一标识,避免重复
  const existingKeys = new Set(
    existingWebhooks.map(wh => `${wh.topic}-${wh.address}`)
  );

  return desiredWebhooks.filter(wh => {
    const key = `${wh.topic}-${wh.callbackUrl}`;
    return !existingKeys.has(key);
  });
}

app.get('/auth/callback', async (req: any, res: any) => {
  console.log('CALLBACK');
  const callback = await shopify.auth.callback({
    rawRequest: req,
    rawResponse: res,
  });

  // 定义你需要的Webhook配置,和addHandlers中的配置保持一致
  const desiredWebhooks = [
    {
      topic: 'PRODUCTS_CREATE',
      callbackUrl: '/webhooks',
      deliveryMethod: DeliveryMethod.Http,
    },
    {
      topic: 'PRODUCTS_UPDATE',
      callbackUrl: '/webhooks',
      deliveryMethod: DeliveryMethod.Http,
    },
  ];

  // 检查缺失的Webhook
  const missingWebhooks = await checkExistingWebhooks(callback.session, desiredWebhooks);

  if (missingWebhooks.length > 0) {
    // 仅注册缺失的Webhook
    const response = await shopify.webhooks.register({
      session: callback.session,
      webhooks: missingWebhooks,
    });

    console.log('注册结果:', response);

    // 逐个检查注册状态
    missingWebhooks.forEach(wh => {
      const result = response[wh.topic]?.[0];
      if (!result?.success) {
        console.log(`注册${wh.topic}失败: ${result?.result}`);
      } else {
        console.log(`成功注册${wh.topic} Webhook`);
      }
    });
  } else {
    console.log('所有需要的Webhook已存在,无需重复注册');
  }

  console.log(callback);
  res.send('AUTH');
});

关键说明

  • 唯一标识判断:用topic+callbackUrl组合作为Webhook的唯一标识,确保和已注册的Webhook精确匹配
  • API版本配置:确保process.env.SHOPIFY_API_VERSION已正确设置,避免API调用报错
  • 自动去重替代方案:Shopify的webhooks.register方法本身会尝试去重,但如果你的场景下仍出现重复,手动检查是最可靠的方式

内容的提问来源于stack exchange,提问作者reacter777

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:33:14