3

In the previous version I used to get the current shop name is like this:

router.get("/api/app", async (ctx) => {
  let shop = ctx.session.shop;
});

but, in the new version, i can't get the current shop name using ctx.session.shop, i don't see any object on the log named name, and also the session token, i do see session token and shop name on the reffer object, but i think there is another way where i can access those directly.

so, how do i get the current shop name ? here is my code:

import "@babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "@shopify/koa-shopify-auth";
import Shopify, { ApiVersion } from "@shopify/shopify-api";
import Koa from "koa";
import session from "koa-session";
import next from "next";
import Router from "koa-router";
import koaBody from "koa-body";

dotenv.config();
const port = parseInt(process.env.PORT, 10) || 8081;
const dev = process.env.NODE_ENV !== "production";
const app = next({
  dev,
});
const handle = app.getRequestHandler();

Shopify.Context.initialize({
  API_KEY: process.env.SHOPIFY_API_KEY,
  API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
  SCOPES: process.env.SCOPES.split(","),
  HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
  API_VERSION: ApiVersion.October20,
  IS_EMBEDDED_APP: true,
  SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});

// Storing the currently active shops in memory will force them to re-login when your server restarts. You should
// persist this object in your app.
const ACTIVE_SHOPIFY_SHOPS = {};

const server = new Koa();
const router = new Router();

router.get("/api/test", async (ctx) => {
  return (ctx.body = ctx.session);
});



app.prepare().then(async () => {
  server.keys = [Shopify.Context.API_SECRET_KEY];

  server.use(
    session(
      {
        sameSite: "none",
        secure: true,
      },
      server
    )
  );

  server.use(
    createShopifyAuth({
      async afterAuth(ctx) {
        // Access token and shop available in ctx.state.shopify
        const { shop, accessToken, scope } = ctx.state.shopify;
        const host = ctx.query.host;
        ACTIVE_SHOPIFY_SHOPS[shop] = scope;

        const response = await Shopify.Webhooks.Registry.register({
          shop,
          accessToken,
          path: "/webhooks",
          topic: "APP_UNINSTALLED",
          webhookHandler: async (topic, shop, body) =>
            delete ACTIVE_SHOPIFY_SHOPS[shop],
        });

        if (!response.success) {
          console.log(
            `Failed to register APP_UNINSTALLED webhook: ${response.result}`
          );
        }

        // Redirect to app with shop parameter upon auth
        ctx.redirect(`/?shop=${shop}&host=${host}`);
      },
    })
  );

  const handleRequest = async (ctx) => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
  };

  router.get("/", async (ctx) => {
    const shop = ctx.query.shop;

    // This shop hasn't been seen yet, go through OAuth to create a session
    if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
      ctx.redirect(`/auth?shop=${shop}`);
    } else {
      await handleRequest(ctx);
    }
  });

  router.post("/webhooks", async (ctx) => {
    try {
      await Shopify.Webhooks.Registry.process(ctx.req, ctx.res);
      console.log(`Webhook processed, returned status code 200`);
    } catch (error) {
      console.log(`Failed to process webhook: ${error}`);
    }
  });

  router.post(
    "/graphql",
    verifyRequest({ returnHeader: true }),
    async (ctx, next) => {
      await Shopify.Utils.graphqlProxy(ctx.req, ctx.res);
    }
  );

  router.get("(/_next/static/.*)", handleRequest); // Static content is clear
  router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear
  router.get("(.*)", verifyRequest(), handleRequest); // Everything else must have sessions

  server.use(router.allowedMethods());
  server.use(router.routes());
  server.listen(port, () => {
    console.log(`> Ready on http://localhost:${port}`);
  });
});

Thanks in advance.

MHT
  • 37
  • 11

1 Answers1

2

Here's how to do it inside your server.js file: For your index route i.e router.get("/") set the cookie for shop name that can be fetched as shown below. Once the cookie is set when the shop owners opens the app from the admin, now when you open the app from your redirect link which is set in partners portal usually ngrock then the shop name will be set automatically from the cookie set earlier

Full Code:

    router.get("/", async ctx => {
    const shop = ctx.query.shop
    if (shop) {
        console.log("setting cookie");
        ctx.cookies.set("shop_name", shop, {
            secure: true,
            sameSite: 'none',
            httpOnly: false
        })
    }

    if (ctx.request.header.cookie) {
        var cookies_fetched = parseCookie(ctx.request.header.cookie)

        // This shop hasn't been seen yet, go through OAuth to create a session
        if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
            ctx.redirect(`/auth?shop=${cookies_fetched.shop_name}`)
        } else {
            await handleRequest(ctx)
        }
    } else {
        if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
            ctx.redirect(`/auth?shop=${shop}`)
        } else {
            await handleRequest(ctx)
        }
    }
})
Surbhit Rao
  • 625
  • 6
  • 14