Skip to content

Instantly share code, notes, and snippets.

@devdarren7
Last active December 6, 2018 13:40
Show Gist options
  • Select an option

  • Save devdarren7/5c8058d08f1fad0ed44a4fdf8d58179b to your computer and use it in GitHub Desktop.

Select an option

Save devdarren7/5c8058d08f1fad0ed44a4fdf8d58179b to your computer and use it in GitHub Desktop.
const express = require('express');
const app = express();
app.use(express.static(__dirname + '/assets'));
const dotenv = require('dotenv').config();
const crypto = require('crypto');
const cookie = require('cookie');
const nonce = require('nonce')();
const querystring = require('querystring');
const request = require('request-promise');
const apiKey = process.env.SHOPIFY_API_KEY;
const apiSecret = process.env.SHOPIFY_API_SECRET;
const scopes = 'read_products';
const forwardingAddress = "https://arcane-savannah-70578.herokuapp.com/"; // Replace this with your HTTPS Forwarding address
// https://687d8c81.ngrok.io/shopify?shop=dreamcatcherscom.myshopify.com
const FroalaEditor = require('froala-editor');
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
const server_port = process.env.YOUR_PORT || process.env.PORT || 80;
const server_host = process.env.YOUR_HOST || '0.0.0.0';
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;
const stateCookie = cookie.parse(req.headers.cookie).state;
if (state !== stateCookie) {
return res.status(403).send('Request origin cannot be verified');
}
if (shop && hmac && code) {
// DONE: Validate request is from Shopify
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;
try {
hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac)
} catch (e) {
hashEquals = false;
};
if (!hashEquals) {
return res.status(400).send('HMAC validation failed');
}
// DONE: Exchange temporary code for a permanent access token
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/metafields.json';
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken,
};
const info = { json: accessTokenPayload } ;
request.get(shopRequestUrl, { headers: shopRequestHeaders })
.then((shopResponse) => {
res.status(200).send(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');
}
});
app.listen(server_port, server_host, function() {
console.log('Listening on port %d', server_port);
console.log(__dirname);
});
app.get('/', function (req, res) {
res.render('map',
{ title : 'Home',
api_Key: apiKey,
shop : req.headers.cookie && cookie.parse(req.headers.cookie).shop,
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment