如何检查Webhook是否存在并避免重复创建?
解决Shopify重复注册Webhook的问题
核心思路
每次认证回调时先查询店铺已注册的Webhook列表,对比你需要的Webhook配置(topic+callbackUrl+deliveryMethod),仅注册不存在的Webhook,避免重复创建。
实现步骤
- 新增Webhook检查函数:通过Shopify Rest API获取已有的Webhook,筛选出缺失的目标Webhook
- 修改认证回调逻辑:在调用
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
相关产品推荐
相关产品推荐

