Shopify / shopify-app-js

MIT License
275 stars 108 forks source link

`ensureInstalledOnShop` did not receive a shop query argument #161

Open kelreel opened 1 year ago

kelreel commented 1 year ago

Issue summary

During moderation in the Appstore, I have already received a reject several times. There are errors in the moderator's account when changing the subscription plan. I see in the production logs ensureInstalledOnShop did not receive a shop query argument. I can't figure out why this is happening. There is no such error on my dev/prod accounts, including test staff accounts.

How can more data be collected when this happens? I thought the issue would be solved after closing https://github.com/Shopify/shopify-app-js/issues/94, but these errors are again...

Packages:

Logs:

[shopify-app/ERROR] ensureInstalledOnShop did not receive a shop query argument | {shop: undefined}
[shopify-app/INFO] Running ensureInstalledOnShop
[shopify-app/ERROR] ensureInstalledOnShop did not receive a shop query argument | {shop: undefined}
[shopify-app/ERROR] ensureInstalledOnShop did not receive a shop query argument | {shop: undefined}
[shopify-app/INFO] Running ensureInstalledOnShop
....

Shopify.ts

export const shopify = shopifyApp({
    api: {
        apiKey: process.env.SHOPIFY_API_KEY!,
        apiSecretKey: process.env.SHOPIFY_API_SECRET!,
        scopes: process.env.SCOPES!.split(','),
        hostName: process.env.HOST!.replace(/https?:\/\//, ''),
        hostScheme: 'https',
        apiVersion: LATEST_API_VERSION,
        isEmbeddedApp: true,
        logger: {
            level: LogSeverity.Debug,
        },
        ...(process.env.SHOP_CUSTOM_DOMAIN && {
            customShopDomains: [process.env.SHOP_CUSTOM_DOMAIN],
        }),
        billing: {
            [BillingPlan.Pro]: {
                interval: BillingInterval.Every30Days,
                amount: BillingPlans.Pro.price,
                currencyCode: 'USD',
                replacementBehavior: BillingReplacementBehavior.ApplyImmediately,
                trialDays: 3,
            },
        },
    },
    webhooks: {
        path: '/api/webhooks',
    },
    auth: {
        path: '/api/auth',
        callbackPath: '/api/auth/callback',
    },
    sessionStorage: new PostgreSQLSessionStorage(new URL(process.env.POSTGRES_URL!), {
        sessionTableName: 'shopify_sessions',
    }),
    useOnlineTokens: true,
});

App.ts

export async function createServer(isProd = process.env.NODE_ENV === 'production') {
    const app = express();

    // CSP x-frame header
    app.use(async (req, res, next) => {
        const shop = shopify.api.utils.sanitizeShop(req.query.shop as string);

        res.setHeader(
            'Content-Security-Policy',
            `frame-ancestors https://admin.shopify.com ${shop ? 'https://' + encodeURIComponent(shop) : ''}`,
        );
        next();
    });

    app.get(shopify.config.auth.path, shopify.auth.begin());
    app.get(
        shopify.config.auth.callbackPath,
        shopify.auth.callback(),
        async (req, res, next) => {
            const session = res.locals.shopify.session;
            await saveShopData(session);
            initProductWidget(session.shop);
            next();
        },
        shopify.redirectToShopifyOrAppRoot(),
    );

    app.post(shopify.config.webhooks.path, shopify.processWebhooks({ webhookHandlers }));

    // All endpoints after this point will require an active session
    app.use('/api/*', shopify.validateAuthenticatedSession());

    // All endpoints after this point will have access to a request.body
    // attribute, as a result of the express.json() middleware
    app.use(express.json());
    app.use(urlencoded({ extended: true }));

    app.post('/api/graphql', async (req: Request, res) => {
        try {
            await shopify.api.clients
                .graphqlProxy({
                    session: res.locals.shopify.session as Session,
                    rawBody: req.body,
                })
                .then(data => res.send(data.body))
                .catch(e => res.status(400).send({ errors: e?.response?.errors }));
        } catch (e) {
            console.log(e);
        }
    });

    // controllers...
    app.use('/api/products', ProductsController);
    app.use('/api/files', FilesController);
    app.use('/api/widgets', WidgetsController);

    if (isProd) {
        const compression = await import('compression').then(({ default: fn }) => fn);
        const serveStatic = await import('serve-static').then(({ default: fn }) => fn);
        app.use(compression());
        app.use(serveStatic(PROD_INDEX_PATH, { index: false }));
    }

    app.use('/*', shopify.ensureInstalledOnShop(), async (req, res, next) => {
        const htmlFile = join(isProd ? PROD_INDEX_PATH : DEV_INDEX_PATH, 'index.html');

        return res.status(200).set('Content-Type', 'text/html').send(readFileSync(htmlFile));
    });

    return { app };
}
github-actions[bot] commented 1 month ago

We're labeling this issue as stale because there hasn't been any activity on it for 60 days. While the issue will stay open and we hope to resolve it, this helps us prioritize community requests.

You can add a comment to remove the label if it's still relevant, and we can re-evaluate it.

oribenez commented 1 month ago

not stale

arsamFarooq commented 1 month ago

Not stale My app was working perfectly fine yesterday. Now i didn't updated any thing in the code. I started the dev server today again and now i am getting this error

nadavboa commented 1 week ago

Same Error: [shopify-app/ERROR] ensureInstalledOnShop did not receive a shop query argument | {shop: undefined }