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运行之后的临时域名,我需要如何保证正常处理呢?能详细的写出步骤和解答吗?
