#Lucas974-webook-sig

1 messages · Page 1 of 1 (latest)

pliant sluice
#

Hi there!

#

What are you using for your backend here?

regal patrol
#

express.js

below a sample of webhook.js:

const stripe = require('stripe')(process.env.SK_STRIPE);
const signStripe = process.env.SIGNATURE


module.exports = async (req, res) => {
    const sig = req.headers['stripe-signature'];
    let event;
    try {
        event = stripe.webhooks.constructEvent(req.body, sig, signStripe);
    }
    catch (err) {
        res.status(400).send(`Webhook Error: ${err.message}`);
    }
#

and app.js:

require('dotenv').config();

const webhook = require('./webhook');

const express = require('express');
const app = express();

...

app.post('/webhook', express.raw({type: 'application/json'}), webhook);
#

I really don't understand why this doesn't work :/

pliant sluice
#

How are you testing?

#

Are you forwarding via the CLI?

regal patrol
#

using payment link in test mode

pliant sluice
#

Or do you have a HTTPS endpoint?

regal patrol
#

yep

#

this is https

#

I can give you the endpoint if you want

pliant sluice
#

No that's okay

#

Are you using express.json anywhere?

#

Can you show me your whole endpoint code?

regal patrol
#

yep

#

app.js:

require('dotenv').config();

const webhook = require('./webhook');

const express = require('express');
const app = express();

const https = require('https');
const fs = require('fs');

const PORT = process.env.PORT;

app.post('/webhook', express.raw({type: 'application/json'}), webhook);

app.get("/", (req, res) => {
        res.send(`Backend is running on port ${PORT}`);
});

const options = {
  key: fs.readFileSync('/etc/ssl/private/aa.pem'),
  cert: fs.readFileSync('/etc/ssl/aa.fullchain.pem')
};

https.createServer(options, app).listen(PORT, () => {
  console.log(`Running backend on port ${PORT}`);
});
#

and webhook.js:

const stripe = require('stripe')(process.env.SK_STRIPE);
const signStripe = process.env.SIGNATURE

const { formatDate } = require('./utils');
const Payment = require('./db');

module.exports = async (req, res) => {
    const sig = req.headers['stripe-signature'];
    let event;
    try {
        event = stripe.webhooks.constructEvent(req.body, sig, signStripe);
    }
    catch (err) {
        res.status(400).send(`Webhook Error: ${err.message}`);
    }

    const id = req.body?.data?.object?.id;
    if (!id) {
        console.error('Invalid webhook data:', req.body);
        return res.sendStatus(400);
    }
    res.status(200).send('Webhook received successfully');
    try {
        const data = await stripe.paymentIntents.retrieve(
            id, { expand: ['payment_method'] }
        );
        const paymentData = {
            pid: id,
            date: formatDate(data.payment_method.created),
            name: data.payment_method.billing_details.name,
            email: data.payment_method.billing_details.email,
            country: data.payment_method.billing_details.address.country,
            type: data.payment_method.card.brand,
            last4: data.payment_method.card.last4,
        };
        console.log(paymentData);
        const payment = new Payment(paymentData);
        await payment.save();
    } catch(error) {
        console.error('Error retrieving payment intent:', error);
    }
}
pliant sluice
#

Hmm okay

#

Right before event = stripe.webhooks.constructEvent(req.body, sig, signStripe); can you log out req.body and tell me what you see?

regal patrol
#

ok doing it

#

Get this:

<Buffer 7b 0a 20 20 22 69 64 22 3a 20 22 65 76 74 5f 33 4d 6c 45 53 54 47 78 62 6f 48 61 6c 4e 6f 67 30 32 33 73 42 4d 50 52 22 2c 0a 20 20 22 6f 62 6a 65 63 ... 1850 more bytes>
Invalid webhook data: <Buffer 7b 0a 20 20 22 69 64 22 3a 20 22 65 76 74 5f 33 4d 6c 45 53 54 47 78 62 6f 48 61 6c 4e 6f 67 30 32 33 73 42 4d 50 52 22 2c 0a 20 20 22 6f 62 6a 65 63 ... 1850 more bytes>

#

I did it like that:

 try {
        console.log(req.body);
        event = stripe.webhooks.constructEvent(req.body, sig, signStripe);
    }
pliant sluice
#

Okay that is what it should look like

#

Can you log out your secret key and ensure it matches the one in your Dashboard for that endpoint

regal patrol
#

ok doing it...

#

they are same

#

whsec_ZV9Fh...

#

Really I don't understand where is the issue :/

pliant sluice
#

Hmmm can you show me the full error message?

regal patrol
#

this is just:
Invalid webhook data: <Buffer 7b 0a 20 20 22 69 64 22 3a 20 22 65 76 74 5f 33 4d 6c 45 5a 54 47 78 62 6f 48 61 6c 4e 6f 67 31 66 7a 47 54 72 30 39 22 2c 0a 20 20 22 6f 62 6a 65 63 ... 1850 more bytes>

pliant sluice
#

Where do you see that error exactly?

regal patrol
#

npm run dev

#

I proceed to a payment

#

then it shows up on my backend

#

If I remove the signing check, I can see the payment done and get the details (email.. to record in my mongodb)

pliant sluice
#

"It shows up on my backend" -- what does this mean?

#

That error shows up?

#

Do you have stack trace with the line that is hitting that error?

regal patrol
#

the error comes from here:
catch (err) {
res.status(400).send(Webhook Error: ${err.message});
}

pliant sluice
#

Okay can you log that whole err?

regal patrol
#

how?

pliant sluice
#

console.log("err: ", err) above that res.status(400)

regal patrol
#

hum

#

regarding the code

#

I find something:

pliant sluice
#

The other thing you can do actually is provide me an Event ID

regal patrol
#
module.exports = async (req, res) => {
    const sig = req.headers['stripe-signature'];
    let event;
    try {
        console.log(signStripe);
        event = stripe.webhooks.constructEvent(req.body, sig, signStripe);
    }
    catch (err) {
        res.status(400).send(`Webhook Error: ${err.message}`);
    }

    const id = req.body?.data?.object?.id;
    if (!id) {
        console.error('Invalid webhook data:', req.body);
        return res.sendStatus(400);
    }
#

the error I get is not from the signing check but the code:

const id = req.body?.data?.object?.id;

 if (!id) {
        console.error('Invalid webhook data:', req.body);
        return res.sendStatus(400);
    }
#

are you ok with this?

pliant sluice
#

Oh okay then yeah that is why

regal patrol
#

This doesnt work anymore since I use express.raw

#

but I don't know how I can resolve this

pliant sluice
#

Well you need to find out why (!id)

#

But really you should be using a case statement here

#

Instead of checking that every object has an ID

regal patrol
#

like the code on the website

#

but for you the signing is working, right?

pliant sluice
#

Using switch and then having a case statement for each Event type you want to handle

#

Yes the signing works fine if you are making it to that line

regal patrol
#

ok, now i need to tune the rest of the code

#

thank you very much for your help

#

you re awesome

#

merci beaucoup!