Last active
May 19, 2019 21:05
-
-
Save devdarren7/a42201816639d4252263c5399c95e8f6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const express = require('express'); | |
| const Shop = require('../models/Shop'); | |
| const Shopify = require('shopify-node-api'); | |
| const config = require('../config'); | |
| const generateNonce = require('../helpers').generateNonce; | |
| const buildWebhook = require('../helpers').buildWebhook; | |
| const bodyParser = require('body-parser'); | |
| const url = require('url'); | |
| const querystring = require('querystring'); | |
| const router = express.Router(); | |
| var app = express(); | |
| app.use(bodyParser.json()); | |
| app.use(bodyParser.urlencoded({ extended: false })); | |
| let shopAPI ; | |
| let shopName ; | |
| let redirectURI | |
| const nonce = generateNonce(); | |
| console.log(generateNonce); | |
| function BuildAuth( req, res , next){ | |
| var shop = req.query.shop; | |
| console.log(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'); | |
| } | |
| } | |
| function Auth(req,res,next){ | |
| const params = req.query; | |
| const query = Shop.findOne({ shopify_domain: params.shop }).exec(); | |
| query.then((result) => { | |
| const shop = result; | |
| const shopAPI = new Shopify({ | |
| shop: params.shop, | |
| shopify_api_key: config.SHOPIFY_API_KEY, | |
| shopify_shared_secret: config.SHOPIFY_SHARED_SECRET, | |
| nonce: shop.nonce, | |
| }); | |
| shopAPI.exchange_temporary_token(params, (error, data) => { | |
| if (error) { | |
| console.log(error); | |
| res.redirect('/error'); | |
| } | |
| console.log(data); | |
| shop.accessToken = data.access_token; | |
| shop.isActive = true; | |
| shop.save((saveError) => { | |
| if (saveError) { | |
| console.log('Cannot save shop: ', saveError); | |
| res.redirect('/error'); | |
| } | |
| if (config.APP_STORE_NAME) { | |
| res.redirect(`https://${shop.shopify_domain}/admin/apps/${config.APP_STORE_NAME}`); | |
| } else { | |
| res.redirect(`https://${shop.shopify_domain}/admin/apps`); | |
| } | |
| }); | |
| }); | |
| }); | |
| } | |
| function queryDB(req,res ,next){ | |
| var shopName = req.query.shop + '.myshopify.com'; | |
| const query = Shop.findOne({ shopify_domain: shopName }).exec(); | |
| shopAPI = new Shopify({ | |
| shop: shopName, | |
| shopify_api_key: config.SHOPIFY_API_KEY, | |
| shopify_shared_secret: config.SHOPIFY_SHARED_SECRET, | |
| shopify_scope: config.APP_SCOPE, | |
| nonce, | |
| redirect_uri: `${config.APP_URI}/install/callback`, | |
| }); | |
| var redirectURI = shopAPI.buildAuthURL(); | |
| next() | |
| } | |
| function saveDomain(req,res ,next){ | |
| let save; | |
| const shop = shopAPI; | |
| if (!shop) { | |
| save = new Shop({ shopify_domain: shopName, nonce }).save(); | |
| } else { | |
| shop.shopify_domain = shopName; | |
| shop.nonce = nonce; | |
| Shop({ shopify_domain: shopName, nonce }).save(); | |
| } | |
| } | |
| function 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/api/2019-04/shop.json'; | |
| const shopRequestHeaders = { | |
| 'X-Shopify-Access-Token': accessToken, | |
| }; | |
| request.get(shopRequestUrl, { headers: shopRequestHeaders }) | |
| .then((shopResponse) => { | |
| 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'); | |
| } | |
| } | |
| let shop ; | |
| router.all('/', BuildAuth, queryDB ,(req, res) => { | |
| }); | |
| module.exports = router; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment