scriptTag,webhook问题求教!!!

Topic summary

一位前端开发者在开发 Shopify 应用时遇到两个主要问题:

问题1:APP_UNINSTALLED Webhook 失败

  • 使用 yarn dev 生成的临时 Cloudflare 域名导致 webhook 端点返回 503 错误,失败率 100%
  • 原因:每次启动开发服务器时临时 URL 会变化,但 Shopify 不会自动更新 webhook URL

建议解决方案:

  • 启动开发服务器后运行部署命令(如 npm run shopify app deploy
  • 验证 shopify.app.toml 文件中的 webhook 配置是否正确
  • 考虑禁用开发环境的 Cloudflare 代理
  • 使用 shopify webhook trigger app/uninstalled 手动测试
  • 开发者决定部署到自有服务器以获得固定回调地址

问题2:ScriptTag 注入失败

  • 已通过 ScriptTag 注入 JS 文件到产品页面实现 UI 自定义
  • JS 文件本身没有问题且可正常访问(存储在 CDN)
  • 在开发商店安装应用后脚本未执行
  • Webhook 验证成功但注入日志未显示执行记录

当前状态: 第二个问题尚未解决,开发者寻求进一步帮助定位 ScriptTag 不执行的具体原因。

Summarized with AI on October 25. AI used: claude-sonnet-4-5-20250929.

help!我是一名刚接触shopify的前端开发人员,我在开发一款shopify应用程序,我现在在我的开发商店进行开发与测试,我想要更改产品页面上面的规格自定义布局和表单项目,我使用ScriptTag来注入脚本,当前脚本文件就是简单的demo,我将我这个js文件存储到cdn公网上,我能保证下载与查看,我在项目中的shopify.service.js文件中部分代码如下

export async function registerScriptTag(admin) {
  const scriptSrc = 'https://res-cdn.jiajiaxingxuan.com/shopify/custom-variant-picker.js';
  
  try {
    // 检查 admin 对象是否可用
    if (!admin || !admin.rest) {
      console.log('registerScriptTag Admin client not ready, skipping ScriptTag registration');
      return;
    }

    // 先检查是否已存在相同的 script_tag
    const existing = await admin.rest.get({ path: 'script_tags' });
    const alreadyExists = existing.body.script_tags.find(tag =>
      tag.src === scriptSrc  // 使用完全匹配,确保URL一致
    );

    if (alreadyExists) {
      console.log(`ScriptTag already exists: ${scriptSrc}`);
      return;
    }

    // 创建新的 ScriptTag
    const response = await admin.rest.post({
      path: 'script_tags',
      data: {
        script_tag: {
          event: 'onload',
          src: scriptSrc
        }
      },
      type: 'application/json',
    });

    console.log(`ScriptTag created:`, response.body);
  } catch (error) {
    console.error("Error creating ScriptTag:", error);
  }
}


const shopify = shopifyApp({
  apiKey: process.env.SHOPIFY_API_KEY,
  apiSecretKey: process.env.SHOPIFY_API_SECRET || "",
  apiVersion: LATEST_API_VERSION,
  scopes: process.env.SCOPES?.split(","),
  appUrl: process.env.SHOPIFY_APP_URL || "",
  authPathPrefix: "/auth",
  sessionStorage: new PrismaSessionStorage(prisma),
  distribution: AppDistribution.AppStore,
  hooks: {
    afterAuth: async ({ session, admin, logger }) => {
      try {
        logger.info(`After auth hook triggered for shop: ${session.shop}`);
        console.log('After auth hook triggered for shop: ', session.shop);
        await registerScriptTag(admin);
        logger.info(`ScriptTag registration completed for shop: ${session.shop}`);
        console.log('ScriptTag registration completed for shop: ', session.shop);
      } catch (error) {
        logger.error(`Error in afterAuth hook:`, error);
        console.error('Error in afterAuth hook: ', error);
      }
    },
  },
  future: {
    unstable_newEmbeddedAuthStrategy: true,
    // removeRest: true,
  },
  ...(process.env.SHOP_CUSTOM_DOMAIN
    ? { customShopDomains: [process.env.SHOP_CUSTOM_DOMAIN] }
    : {}),
});

我将我的应用 shopify app deploy 部署完成我的开发商店去访问产品页并未变化。控制台也未输出相关日志,我需要如何操作呢。问题二,我在webhooks.app.uninstalled文件中进行清除处理,

import { authenticate } from "../shopify.server";
import db from "../db.server";

export const action = async ({ request }) => {
  try {
    // 校验 webhook 并获取 shop、admin client
    const { topic, shop, admin } = await authenticate.webhook(request);

    console.log(`🔔 Received ${topic} webhook for shop: ${shop}`);

    if (!shop) {
      console.warn("Shop not found in webhook payload");
      return new Response("Bad Request", { status: 400 });
    }

    // 1️⃣ 清理数据库会话
    await db.session.deleteMany({ where: { shop } });
    console.log(`✅ Cleaned up sessions for shop: ${shop}`);

    // 2️⃣ 删除 ScriptTag
    const scriptSrc = "https://res-cdn.jiajiaxingxuan.com/shopify/custom-variant-picker.js";

    if (admin) {
      try {
        // 查询已有 ScriptTag
        const listRes = await admin.graphql({
          query: `
            {
              scriptTags(first: 50) {
                nodes { id src }
              }
            }
          `
        });

        const targets = listRes?.body?.data?.scriptTags?.nodes?.filter(n => n?.src === scriptSrc) || [];

        for (const tag of targets) {
          try {
            const delRes = await admin.graphql({
              query: `
                mutation deleteScriptTag($id: ID!) {
                  scriptTagDelete(id: $id) {
                    deletedScriptTagId
                    userErrors { field message }
                  }
                }
              `,
              variables: { id: tag.id },
            });

            const errs = delRes?.body?.data?.scriptTagDelete?.userErrors;
            if (errs && errs.length > 0) {
              console.error("scriptTagDelete userErrors:", errs);
            } else {
              console.log(`✅ ScriptTag deleted: ${tag.id}`);
            }
          } catch (e) {
            console.error("❌ Failed to delete ScriptTag:", tag?.id, e);
          }
        }
      } catch (e) {
        console.error("❌ Failed to list ScriptTags:", e);
      }
    } else {
      console.warn("Admin client not available, skipped ScriptTag deletion");
    }

    return new Response("OK", { status: 200 });
  } catch (err) {
    console.error("❌ Error in APP_UNINSTALLED webhook:", err);
    return new Response("Unauthorized", { status: 401 });
  }
};

这是我的代码,但是在我开发应用后台→监控发现app/uninstalled失败率100%, 我看了下是503的错误,这个请求访问的端点是https://identified-ottawa-historic-auckland.trycloudflare.com/webhooks/app/uninstalled, yarn dev运行之后的临时域名,我需要如何保证正常处理呢?能详细的写出步骤和解答吗?

@transparency 您好,

感谢您分享问题详情。根据您的描述,app/uninstalled webhook 的 503 错误和 100% 的失败率可能与临时开发 URL 的处理方式有关。

以下是一些帮助您解决此问题的关键步骤:

启动开发服务器后部署:
运行 yarn dev 时,临时 Cloudflare URL 每次都会发生变化,但 Shopify 不会自动更新 webhook URL 以进行匹配。启动开发服务器后运行部署命令(例如,npm run shopify app deploy)可确保 Shopify 为 webhook 注册正确的 URL。

验证 shopify.app.toml 配置:
确保您的 shopify.app.toml 文件中正确声明了 app/uninstalled 的 webhook 订阅,并指向正确的端点。

在开发过程中避免使用 Cloudflare 代理:
Cloudflare 代理有时会在开发过程中干扰 webhook 的交付。请考虑禁用开发 URL 的代理,以减少潜在问题。

检查服务器可用性:
503 错误通常意味着服务器无法访问。请仔细检查您的开发服务器是否正常运行,并且可以通过 webhook 端点 URL 访问。

手动测试 Webhook 交付:
使用 Shopify CLI 命令 shopify webhook trigger app/uninstalled 模拟 webhook 交付,并验证您的端点是否正确处理 webhook。

遵循以下步骤应该可以帮助您在开发过程中正确处理 app/uninstalled webhook 并消除 503 错误。

如果您需要任何进一步的帮助或希望我审查您的 webhook 处理代码,请随时分享!

thanks! 我决定将当前项目部署到我自己的服务器上,这样我的回调地址应该不会变,可能会规避这个失败的问题,我还有个问题就是使用scriptTag来注入js脚本,以实现产品页的UI自定义,我的js文件是没有问题的。但是我开发商店来安装应用却没有执行脚本运行。能帮我看下具体问题吗?不胜感激


目前我使用开发的临时域名来验证卸载的webhook是能够成功执行和打印的,但是我的注入日志是没有执行的,请问如何处理呢?