Rivan
Rivan

Reputation: 55

Stripe Webhook Validation

I keep getting this error:

No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing

I believe it's something to do with the middleware that I'm using, but I'm not sure which one. Here's my middlewares

app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "../views"));
app.use(
  favicon(path.join(__dirname, "../public/img/logo", "logo-bg-round.png"))
);
app.use(express.static("public"));
app.use(
  session({
    name: "oauth",
    secret: "PlincoOAUTH2",
    resave: true,
    saveUninitialized: true,
  })
);
app.use(passport.initialize());
app.use(passport.session());
app.use(express.json());
app.configure(socketio());
app.configure(express.rest());
app.use("/projects", new DashboardService());
app.on("connection", (conn) => app.channel("stream").join(conn));
app.publish(() => app.channel("stream"));
app.use("/auth", require("./routes/auth"));
app.use(cors());

Here's my route:

const Stripe = require("stripe");
const stripe = Stripe(
  "sk_test_..."
);

// Stripe requires the raw body to construct the event
app.post(
  "/payments/webhook",
  bodyParser.raw({ type: "application/json" }),
  (req, res) => {
    const sig = req.headers["stripe-signature"];
    const webhookSecret = "whsec_...";
    let event;

    try {
      event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
    } catch (err) {
      // On error, log and return the error message
      console.log(`❌ Error message: ${err.message}`);
      return res.status(400).send(`Webhook Error: ${err.message}`);
    }

    // Successfully constructed event
    console.log("✅ Success:", event.id);

    // Return a response to acknowledge receipt of the event
    res.json({ received: true });
  }
);

I've tried many things and cannot find a solution, how do I fix this?

Upvotes: 0

Views: 958

Answers (1)

floatingLomas
floatingLomas

Reputation: 8727

You're not getting the raw body the way you're doing it. You need to 'exclude' your webhook route from the express.json() body parser like is described here: https://github.com/stripe/stripe-node/blob/master/examples/webhook-signing/node-express/express.js

So instead of

app.use(express.json());

you need something like this:

app.use((req, res, next) => {
  if (req.originalUrl === '/payments/webhook') {
    next();
  } else {
    express.json()(req, res, next);
  }
});

Upvotes: 4

Related Questions