#kyrn0zofficiel_webhooks

1 messages · Page 1 of 1 (latest)

ivory ridgeBOT
#

👋 Welcome to your new thread!

⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1220610432364974161

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

jovial scarabBOT
hollow pond
#
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const router = express.Router();

router.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  let event;

  try {
    event = stripe.webhooks.constructEvent(
        req.body,
        req.headers['stripe-signature'],
        process.env.STRIPE_WEBHOOK_SECRET
      );
    } catch (err) {
    console.log('❌ Error while verifying webhook signature:', err.message);
    return res.sendStatus(400);
  }

  try {
    switch (event.type) {
      case 'invoice.payment_succeeded':
        const invoice = event.data.object;
        console.log('Invoice payment succeeded:', invoice.id);
        break;
      case 'invoice.payment_failed':
        const failedInvoice = event.data.object;
        console.log('Invoice payment failed:', failedInvoice.id);
        break;
      default:
        console.log('Unhandled event type:', event.type);
    }
  } catch (err) {
    console.log('❌ Error handling webhook event:', err.message);
    return res.sendStatus(500);
  }
  res.sendStatus(200);
});

module.exports = (app) => {
    app.use(router);
};
sullen robin
#

Error 400 was returned from your server. With reference to this code, can you share what is the error message?

#

What was logged for err.message?

hollow pond
#

so i log on stripe CLI :

./stripe listen --forward-to localhost:5000/webhook

after that i start my server :
node app.js

and i execute in a other shell :

./stripe trigger payment_intent.succeeded

I get that :

2024-03-22 06:46:05 <-- [400] POST http://localhost:5000/webhook [evt_3Ox0vYB4fjaL5cwe0fzH8teT] <- from CLI

Signature verification is impossible without access to the original signed material. 

Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing``` <- from server
#

i try to explain as i can lol

sullen robin
#

Thanks for sharing! This error message is helpful

hollow pond
#

do you need console log ?

sullen robin
#

Does your node middleware configure parse all the requests to JSON or other format somewhere? For example, if you have app.use(express.json()); prior to your route, this will parse the requests in all JSON, not in raw form before reaching to your webhook function.

hollow pond
#

i show you how i do it :

require('dotenv').config()
const express = require('express');
const authRoutes = require('./routes/authRoutes');
const dataRoutes = require('./routes/dataRoutes');
const uploadRoutes = require('./routes/uploadRoutes');
const stripeRoutes = require('./routes/stripeRoutes');
const webhookRoutes = require('./routes/webhookRoutes');
const cors = require('cors');

const app = express();
const port = 5000;

authRoutes(app);
dataRoutes(app);
uploadRoutes(app);
stripeRoutes(app);
webhookRoutes(app);

app.use(cors());

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

app.use('/data-storage', express.static('data-storage'));

app.use((req, res, next) => {
    console.log(`[${new Date().toLocaleTimeString()}] Request received: ${req.method} ${req.url}`);
    next();
});

app.listen(port, () => {
    console.log(`Server listening at http://localhost:${port}`);
});
#

i don't know if it reply to your question

sullen robin
#

ah! this is the problem:

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

This block of code should be placed before your webhook routes

hollow pond
#

up to router.post('\webhook' ....?

sullen robin
#

Can you try placing this block:

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

before

webhookRoutes(app);
hollow pond
#

ok ok

sullen robin
#

The order of config in node matters

hollow pond
#

like this :

const express = require('express');
const authRoutes = require('./routes/authRoutes');
const dataRoutes = require('./routes/dataRoutes');
const uploadRoutes = require('./routes/uploadRoutes');
const stripeRoutes = require('./routes/stripeRoutes');
const webhookRoutes = require('./routes/webhookRoutes');
const cors = require('cors');

const app = express();
const port = 5000;


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

authRoutes(app);
dataRoutes(app);
uploadRoutes(app);
stripeRoutes(app);
webhookRoutes(app);

app.use(cors());

app.use('/data-storage', express.static('data-storage'));

app.use((req, res, next) => {
    console.log(`[${new Date().toLocaleTimeString()}] Request received: ${req.method} ${req.url}`);
    next();
});

app.listen(port, () => {
    console.log(`Server listening at http://localhost:${port}`);
});
sullen robin
#

yes, can you try it again?

hollow pond
#

yeah

sullen robin
#

have you restarted your server?

hollow pond
#

yeah i restart all

#

CLI and server

sullen robin
#

can you add the log in following code to check if this condition is hit?

if (req.originalUrl === '/webhook') {
    // add log here
    next()
}
hollow pond
#

which log do u need ?

#

body ?

sullen robin
#

any log just to check whether this if block of code is invoked instead of the else block, for example:

console.log("skip parsing to json");
hollow pond
#

it's go in

#
skip parsing to json
❌ Error while verifying webhook signature: Webhook payload must be provided as a string or a Buffer (https://nodejs.org/api/buffer.html) instance representing the _raw_ request body.Payload was provided as a parsed JavaScript object instead. 
Signature verification is impossible without access to the original signed material. 

Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing

skip parsing to json
❌ Error while verifying webhook signature: Webhook payload must be provided as a string or a Buffer (https://nodejs.org/api/buffer.html) instance representing the _raw_ request body.Payload was provided as a parsed JavaScript object instead. 
Signature verification is impossible without access to the original signed material. 

Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing

skip parsing to json
❌ Error while verifying webhook signature: Webhook payload must be provided as a string or a Buffer (https://nodejs.org/api/buffer.html) instance representing the _raw_ request body.Payload was provided as a parsed JavaScript object instead. 
Signature verification is impossible without access to the original signed material. 

Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing
sullen robin
#

Hmm.. somewhere in your code converted the request into JavaScript object

#

do you have other routes before webhook route?

hollow pond
#

let me try to put webhook route first

#

🥳

#

can you explain me why ?

#
    if (req.originalUrl === '/webhook') {
        console.log("skip parsing to json");
        next()
    } else {
      express.json()(req, res, next)
    }
});

webhookRoutes(app);
authRoutes(app);
dataRoutes(app);
uploadRoutes(app);
stripeRoutes(app);

I just put webhookRoutes first

sullen robin
#

ohhh! this is interesting

#

my guess is that express probably check the routes by order and the request body might have been modified along the way

#

great to hear that the problem is resolved

hollow pond
#

perfect

#

maybe can i ask you something else here ? or i need to create a new thread ?

sullen robin
#

this thread is fine! we can continue here

hollow pond
#

fine

#

it's something sofisicate so i prefer whereas my english will be fine to translate from french to make sure that you understand my question as young developper

#

My program is a registration system, and each person who registers is returned to a unique stripe payment link.

My question is, do I need to put my registration forms somewhere?

Do I have to fill my database with statuses like :

  • paid - refused - pending
    with the payment id to update it as soon as I get a request from the webhook, or should I put my server on 'hold' for a request from my webhook?

Translated with DeepL.com (free version)

sullen robin
#

Can you share which integration are you working on? Checkout Session (Stripe hosted payment page) or Payment Element (embedded in your website)?

hollow pond
#

I use Payment Link

sullen robin
#

Payment Link is for multiple usage. Are you looking for one-time or multiple usages?

hollow pond
#

i create one product

#

from this i creat multiple link

#

i have a form and when we submit i create a link with a unique price from the product (like i it cost 50$ and i send a form with 3 product the link will cost 150$)

sullen robin
#

The registration form should be implemented in your website, then you will redirect the customer to the payment link for payment

hollow pond
#

Can I use those custom field as a form and collect it on my database ?

sullen robin
#

It will be additional input field in the Payment Link. I'd recommend giving a try to check if this is what you're looking for

hollow pond
#

Ok

#

And when some use the link

#

Like if the payement pass or not

#

It disable it automatically ?

sullen robin
#

No! Payment Link can be used multiple times, i.e. customer can come back to use the Payment Link to pay again.

If you want to use one-time payment page, I'd recommend using Checkout Session: https://docs.stripe.com/payments/accept-a-payment?platform=web&ui=stripe-hosted

Checkout Session (Stripe hosted payment page) is similar to Payment Link, but it only allows one-time use. If the payment is completed, this payment page will not be available to make payment again.

Securely accept payments online.

hollow pond
#

it's that easy to implement quickly ?

#

and it's work with webhook too ?

sullen robin
#

Yes! It should be easy to implement and it will work with Webhook

hollow pond
#

i need to implement something on sur front

#

or like the payement link it redirect ?

sullen robin
#

The Checkout Session should be created by your server. After it's created, you can then redirect to the customer to this page to complete the payment

hollow pond
#

so i do not have to do a front style or something like that

sullen robin
#

This is up to you how you would like to design your website. Checkout Session is simply a hosted payment page by Stripe.