skip to Main Content

I am using express 4.

in my server.js I have express.json() middleware

require('dotenv').config();
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const errorHandler = require('./_helpers/error-handler');



const app = express();

const port = process.env.PORT || 5000;


app.use(cors());
app.use(express.json()); /////////////////////////////////////////


const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: true});
const connection = mongoose.connection;
connection.once('open', () => {
    console.log("MongoDB database connection established successfully");
});

// routers
app.use('/api/users', require('./routes/api/users/users.controller'));
app.use('/api/orders', require('./routes/api/orders/orders.controller'));
app.use('/shopify/app', require('./routes/shopify/app/shopify.controller'));
app.use('/shopify/app/webhooks', require('./routes/shopify/app/webhooks/webhooks.controller')); ///////////////

app.use(errorHandler);

app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
});

but for '/shopify/app/webhooks' route I need to get raw body so I can create hash
but so far I am receiving Object because I have express.json() middleware.

this is my webhooks.controller.js file

const express = require('express');
const router = express.Router();
const crypto = require('crypto')

const SHOPIFY_API_SECRET_KEY = process.env.SHOPIFY_API_SECRET_KEY;
// router.use(express.raw({ type: "application/json"}));

// routes goes here
router.post('/app/uninstalled', express.raw({ type: 'application/json' }), async (req, res, next) => {
    
    const hmac = req.get('X-Shopify-Hmac-Sha256')
    console.log(req.body);
    // create a hash using the body and our key
    const hash = crypto
        .createHmac('sha256', SHOPIFY_API_SECRET_KEY)
        .update(req.body, 'utf8', 'hex')
        .digest('base64')

    // Compare our hash to Shopify's hash
    if (hash === hmac) {
        // It's a match! All good
        console.log('Phew, it came from Shopifify!')
        res.sendStatus(200)
    } else {
        // No match! This request didn't originate from Shopify
        console.log('Danger! Not from Shopify!')
        res.sendStatus(403)
    }
    
})

what I have tried is in webhooks.controller.js router.use(express.raw({type: "application/json"}))
i thought since I am receiving json object I can use express.raw() middleware that accepts json
but it’s still not working.

2

Answers


  1. You have to place this route BEFORE your app.use(express.json()) middleware and then you can apply the raw middleware directly to that route:

    app.use('/shopify/app/webhooks', express.raw({/* put your options here */}), require('./routes/shopify/app/webhooks/webhooks.controller'));
    

    Keep in mind that this line of code must go physically before your express.json() middleware.

    Login or Signup to reply.
  2. We can get useful info for specific routes before applying body parser.
    So, if you want to get raw body for stripe webhooks.
    We can do like this.

    app.use(bodyParser.json({
      extended: true,
      verify: function (req, res, buf) {
        if (req.originalUrl.endsWith('/stripe/webhooks')) {
          req.rawBody = buf
        }
      }
    }))
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search