#kyrn0zofficiel_webhooks
1 messages · Page 1 of 1 (latest)
👋 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.
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);
};
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?
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
Thanks for sharing! This error message is helpful
do you need console log ?
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.
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
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
up to router.post('\webhook' ....?
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);
ok ok
The order of config in node matters
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}`);
});
yes, can you try it again?
yeah
have you restarted your server?
can you add the log in following code to check if this condition is hit?
if (req.originalUrl === '/webhook') {
// add log here
next()
}
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");
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
Hmm.. somewhere in your code converted the request into JavaScript object
do you have other routes before webhook route?
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
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
perfect
maybe can i ask you something else here ? or i need to create a new thread ?
this thread is fine! we can continue here
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)
Can you share which integration are you working on? Checkout Session (Stripe hosted payment page) or Payment Element (embedded in your website)?
I use Payment Link
Payment Link is for multiple usage. Are you looking for one-time or multiple usages?
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$)
The registration form should be implemented in your website, then you will redirect the customer to the payment link for payment
If you only want to collect information within Stripe hosted payment page, it can be done with using Custom Field: https://docs.stripe.com/payment-links/customize#add-custom-fields
Can I use those custom field as a form and collect it on my database ?
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
Ok
And when some use the link
Like if the payement pass or not
It disable it automatically ?
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.
Yes! It should be easy to implement and it will work with Webhook
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
so i do not have to do a front style or something like that
This is up to you how you would like to design your website. Checkout Session is simply a hosted payment page by Stripe.