Your domain url changes on every server restart and your webhook subscription is only triggered upon installation. This problem only occurs on local development. At the moment, my solution that I could come up with was to have a command script to delete the previous webhook and re-subscribe all webhooks again whenever I restart my server.
import { json } from "@remix-run/node";
import { cors } from "remix-utils/cors";
import { authenticate, unauthenticated } from "../shopify.server";
import dbConnect from "@/db";
import { Session } from "@/modules/session/session.model";
export const loader = async ({ request, response }) => {
await authenticate.admin(request);
return cors(request, response);
}
const webhookTopics = [
'app/uninstalled',
'orders/updated',
// 'orders/create',
'products/update',
'products/delete',
'inventory_levels/update',
'inventory_items/create',
];
export const action = async ({ request }) => {
await dbConnect()
try {
const storeList = await Session.find()
for (const store of storeList) {
const { admin } = await unauthenticated.admin(store.shop);
const subscribedWebhook = await admin.rest.get({
path: `webhooks.json`
});
const subscribedWebhookResponse = await subscribedWebhook.json();
let deleteWebhook = false
// Delete Existing Webhook, Temporary comment incase we need to resubscribe
deleteWebhook = true
for (const currentWebhook of subscribedWebhookResponse.webhooks) {
const deletedWebhook = await admin.rest.delete({
path: `webhooks/${currentWebhook.id}.json`
});
const deletedWebhookResponse = await deletedWebhook.json();
console.log(`Deleted webhook ${currentWebhook.topic}`)
}
for (const topic of webhookTopics) {
let exist = false
subscribedWebhookResponse.webhooks.map(existingWebhook => {
if (existingWebhook.topic === topic && deleteWebhook == false) {
exist = true
}
})
if (exist) {
console.log(`Skip existing webhook ${topic}`)
continue
}
const webhookEndpoint = `${process.env.URL}/webhooks`;
const webhookData = {
webhook: {
topic: topic,
address: webhookEndpoint,
format: 'json',
},
};
const response = await admin.rest.post({
path: `webhooks.json`,
data: webhookData
});
const responseData = await response.json();
if (response.ok) {
console.log(`Webhook for ${topic} successfully created with ID: ${responseData.webhook.id}`);
} else {
console.error(`Failed to create webhook for ${topic}. Error: ${JSON.stringify(responseData)}`);
}
}
}
return cors(request, json({ status: 'success', data: "" }));
} catch (err) {
console.error(err);
return cors(request, json({
status: 'error',
message: 'error'
}, {
status: 500
}));
}
};