skip to Main Content

I am having an issue figuring out how to display html in the admin for an app.

I have followed the ‘Build a Shopify app with Node and Express’ tutorial, and am able to display json of the shop in the Shopify App Admin. However, I am not understanding the next steps of getting any html to display in the app admin. I have tried replacing the end(shopResponse) with a render method, which throws the error ‘request origin cannot be verified’. I have also tried to set up an additional request, but that caused a similar error.


app.get('/shopify', (req, res) => {
  const shop = req.query.shop;
  if (shop) {
    const state = nonce();
    const redirectUri = forwardingAddress + '/shopify/callback';
    const installUrl = 'https://' + shop +
      '/admin/oauth/authorize?client_id=' + apiKey +
      '&scope=' + scopes +
      '&state=' + state +
      '&redirect_uri=' + redirectUri;

    res.cookie('state', state);
    res.redirect(installUrl);
  } else {
    return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request');
  }
});

app.get('/shopify/callback', (req, res) => {
  const { shop, hmac, code, state } = req.query;
  console.log(req.headers)
  var stateCookie = '';

  if (req.headers.cookie) {
    stateCookie = cookie.parse(req.headers.cookie).state; 
  }

  if (state !== stateCookie) {
    return res.status(403).send('Request origin cannot be verified');
  }

  if (shop && hmac && code) {
    const map = Object.assign({}, req.query);
    delete map['signature'];
    delete map['hmac'];
    const message = querystring.stringify(map);
    const providedHmac = Buffer.from(hmac, 'utf-8');
    const generatedHash = Buffer.from(
      crypto
        .createHmac('sha256', apiSecret)
        .update(message)
        .digest('hex'),
        'utf-8'
      );
    let hashEquals = false;
    // timingSafeEqual will prevent any timing attacks. Arguments must be buffers
    try {
      hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac)
    // timingSafeEqual will return an error if the input buffers are not the same length.
    } catch (e) {
      hashEquals = false;
    };

    if (!hashEquals) {
      return res.status(400).send('HMAC validation failed');
    }

    const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
    const accessTokenPayload = {
      client_id: apiKey,
      client_secret: apiSecret,
      code,
    };

    request.post(accessTokenRequestUrl, { json: accessTokenPayload })
    .then((accessTokenResponse) => {
      const accessToken = accessTokenResponse.access_token;
      // DONE: Use access token to make API call to 'shop' endpoint
      const shopRequestUrl = 'https://' + shop + '/admin/api/2019-04/themes.json';
      const shopRequestHeaders = {
        'X-Shopify-Access-Token': accessToken,
      };

      request.get(shopRequestUrl, { headers: shopRequestHeaders })
      .then((shopResponse) => {
        // This is what I have tried replacing with a render method
        res.status(200).end(shopResponse);
      })
      .catch((error) => {
        res.status(error.statusCode).send(error.error.error_description);
      });

    })
    .catch((error) => {
      res.status(error.statusCode).send(error.error.error_description);
    });

  } else {
    res.status(400).send('Required parameters missing');
  }
});

I am expecting to be able to see basic html in the Shopify app admin.

SOLVED

After reading accepted answer, I realized I didn’t need all the auth from the getting started to show the file.

My whitelisted route ended up looking like this:

app.get('/shopify/callback', (req, res) => {

  res.render('pages/index')
});

3

Answers


  1. Edited: I am also new to developing for Shopify and have been spending the last 3 weeks adjusting my Node / Express apps to work with Shopify and I am having bumps in the road as well.

    I just reviewed this tonight (4/25/19) and here is what I did to render / show my index.html page.

    Add this to the top with your other requirements:

    var path = require('path');
    

    Add this path in:

    app.get('/shopify', function (req, res, next) {
    res.sendFile(path.join(__dirname, '../public', 'index.html'));
    }); 
    

    Note: The ‘../pubic’ is the directory right before my ‘index.html’ file. This will probably be different for you, but it should be easy to figure out.

    I also added in this path as well:

    app.get('/', function (req, res, next) {
    res.sendFile(path.join(__dirname, '../public', 'index.html'));
    }); 
    
    Login or Signup to reply.
  2. You don’t display your HTML in Shopify Admin. Instead, you render HTML in your App, and Shopify displays your App embedded inside the Shopify Admin. You have two choices. One is that your App is rendered outside the Admin as per any other normal web App, or two, you choose to render inside the Shopify admin as an embedded App which means your HTML displays inside an iframe Shopify creates for you.

    You should really read the documentation on Shopify Apps before making an App and then asking how Apps display HTML… it is important you understand the basic concept of that.

    Login or Signup to reply.
  3. Once you getting shop json succesfully it means app installed in shopify store successfully

    To Display html in app for store admin you have to create one route in your project which render you to html page like as below

    app.get('/', function (req, res, next) {
        res.render('your html page path');
    }); 
    

    this can render you to html page where you can display html for your app home page

    Now you have to set your domain url in your shopify partner account app setup
    Shopify partner account
    click this url and
    go to your app >> app setup and add your https domain for your app

    https://yourdomain.com/
    

    this root location load when your app open from shopify admin and it display you index html page for your app

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search