#chittykat
1 messages · Page 1 of 1 (latest)
have you tried to run the official samples?
And compare it with your integration and see what is the difference ?
In general your integration is updating the request body (like json or compress middelware)
You need to not apply any middleware to your webhook endpoint, something like this:
https://github.com/stripe/stripe-node/blob/master/examples/webhook-signing/express/main.ts#L23
i currently have this:
app.post(
"/webhook",
express.raw({ type: "application/json" }),
(request, response) => {
console.log(request.body);
const stripeSignature = request.headers["stripe-signature"];
let event;
try {
const stripePayload = request.rawBody || request.body;
event = stripe.webhooks.constructEvent(
stripePayload,
stripeSignature?.toString(),
endpointSecret
);
} catch (err) {
console.log(err);
response.status(400).send(`Webhook Error: ${err.message}`);
return;
}
const metadata = req.body.data.object.metadata;
const cart = JSON.parse(metadata.cart);
if (event.type === "payment_intent.succeeded") {
console.log("Payment succeeded:", event.data.object);
fetch("https://api.tsfeerhuysch.nl:4434/api/completed", {
method: "POST",
headers: {
"Content-Type": "application/json",
sessionkey: cart.cookie,
},
body: JSON.stringify(cart),
})
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.catch((error) => {
// Handle errors
console.error("There was a problem with the fetch operation:", error);
});
} else {
console.log("Payment failed:", event.data.object);
}
response.send();
}
);```
only thing i am applying is a cors
and it still doesn't woprk
What about your global app middelware ?
Have tried to run this sample nodejs app without any update?
https://stripe.com/docs/webhooks/quickstart
Yes that's causing the issue.
i do need the express.json though
you need to do something like this then.
so i need to add this line?
express.raw({type: 'application/json'}),
(req: express.Request, res: express.Response): void => {
and maintain the raw?
thoguh i already have it?
app.post(
"/webhook",
express.raw({ type: "application/json" }),
(request, response) => {```
No you need to use the json middleware for endpoints other than your webhook endpoint
i used this as wel.
const conditionalBodyParser = (req, res, next) => {
if (req.originalUrl === "/webhook") {
next();
} else {
express.json()(req, res, next);
}
};
app.use(conditionalBodyParser);```
still fails though!
Check if you have other middelware in your code
or you are using the correct webhook secret and API key
i am using the test environment key rn
const endpointSecret = "wh..."
So you still have something in your integration that is causing the change of the request body
app.use(cors(corsOptions));
const conditionalBodyParser = (req, res, next) => {
if (req.originalUrl === "/webhook") {
next();
} else {
express.json()(req, res, next);
}
};
app.use(conditionalBodyParser);```
this is all i have that has something to do with app.use.
i guess, but where?
You need to check all your nodejs files and see what coul dbe changing the body of the request
when i create a session i added some metadata:
const session = await stripe.checkout.sessions.create({
line_items: items,
mode: "payment",
success_url: "https://tsfeerhuysch.nl/success.html",
cancel_url: "https://tsfeerhuysch.nl/failed.html",
metadata: {
cart: JSON.stringify(apiCart),
},
});```
could that be it?
no.
You need to focus on things that are causing the change of the request body in your node js integration
Have you had the chance to run this quickstart and test it ?
i have been looking for hours, i am not changing the body anywhere
Without making any change on it ?
not yet
but i am just unsure where the problem could be, because the only possible problem would be in the webhook listener right?
Give it a try and test it first in order to make sure you run and understand a webhook siging
Or is it changed along the path?
yes I understand, that's why I suggest to move forward step by step. First let's make sure you can run the official sample on your env and then you can come back to your integration and see the difference
19|koop | ⚠️ Webhook signature verification failed. No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
19|koop | If a webhook request is being forwarded by a third-party tool, ensure that the exact request body, including JSON formatting and new line style, is preserved.
19|koop | Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing
same thing applies when running the original method.
i am using:
const conditionalBodyParser = (req, res, next) => {
if (req.originalUrl === "/webhook") {
next();
} else {
express.json()(req, res, next);
}
};
app.use(conditionalBodyParser);```
together with:
```js
app.post(
"/webhook",
express.raw({ type: "application/json" }),
(request, response) => {```
Sorry maybe I wasn't enough clear at the beginning.
Did you download the server.js file from here:
https://docs.stripe.com/webhooks/quickstart
And run it ?
Are you facing the issue there ?
Don't use your integration for now. Just to confirm that you are using the write webhook secret and API key.
but that's to run it locally right?
i can't do that, as my whole web is targeted to this api endpoint i currently use
yes
const corsOptions = {
origin: "*",
methods: "GET, POST",
allowedHeaders: "Content-Type, Authorization, sessionkey, cart", // Include 'sessionkey' in the allowed headers
};
app.use(cors(corsOptions));```
could this give problems?
you can run that example in another port and test it
No i don't think so, that's frontend constraints in general
how would i send a webhook request to it?
Hi! I'm taking over from my colleague. Please, give me a moment to catch up.
hahaha did he gave up on me? Sorry for being a hassle but idk, nothing of yall api seems to work with me.
No, my colleague just needed to step away. Let me see...
Is this you latest configuration?
yeah
i can send you my whole api.js code if you'd like. As i see it, i use no middlware at all.
That would be good.
can i dm it you, because i got some keys etc in there
Ok, could you just place the webhook handler on the very top, before any middleware at all, and see what happens?
sure
You are testing locally, right?
not anymore. I am hosting the api on my vps now
i can't send you a dm btw as it's closed for messages i think.
Yeah, we don't do DMs normally. Then, if my colleagues need to jump in they wouldn't see the code too.
Do you mind removing the keys and sharing here?
Does it work locally?
sure.
nope.
Let's find out why it doesn't work there first.
this is my code atm
Do you mind doing this ☝️ and letting me know if it works like that?
sure.
In conditionalBodyParser, next(); will take the execution to cors middleware, and not to the handler directly, which might be the problem.
owh, so we need to remove the next?
I don't know now, I just want us to test it with the clean app.post("/webhook", ...) handler being above everything else. Just after const app = express();
okay
still same error
i can only bring it till here, as i need to use the bodyparser
Why can't you bring it up to the const app = express();? e.g.
const app = express();
app.post(
"/webhook",
...
Could you please use just request.body here: const stripePayload = request.rawBody || request.body;?
this is my hosted endpoint
sure
i did it, same issue occuring still.
Do you think there might be middleware in front of your VPS?
i am using a galaxygate vps, not entirely sure. Would have to ask.
do you know a fast way to check that?
Still, it first must work on your local. Becase if it doesn't work on VPS and on local, the code is likely the source of the problem, not the networking config.
Might be worth contacting support, but it's first worth checking on local.
i will first try it on local.
i tried using the stripe cli online but it gave me this error
I had to delete your code since there were secret keys.
I strongly recommend you to roll the keys now.
oopsie, sorry!
request.headers["stripe-signature"]; Are you sure this is not empty?
i will log it right away
t=1708951248,v1=3e45c5d076588579ace728ccfcdd85af6ae21db793f979b6bab69b677b324909,v0=9bbd7d091a3334f9f770b8e9244cbafd86020c0ad284d95c24724f633257fd6a
this was the header
it for sure isn't empty.
also, i talked to gaalxyagte. They don't add any middlewares, everything of the vps was delivered clean.
Looks fine.
Why are you adding toString() to stripeSignature?.toString(),?
Maybe that's the problem
it was from a previous solution i found on github
it's removed, still same thing
this is so strange
let me know if i should send you more code or something
i am lost at this point
What webhook secret are you using?
the wh test one
// This is your Stripe CLI webhook secret for testing your endpoint locally.
they say it's for local only??
I am not using it on local rn.
Maybe that's the problem?
where can i find the real key?
The one for local testing with CLI will be displayed in the logs.
The real one can be found on the Dashboard.
owh then i need the real one!
But you said it doesn't work on local too.
icouldn't. try local yet
.
so i have 2 questions:
- can i basically use the stripe test key so that i don't need to create real payments, and then use the real webhook key?
Or do they need to both be either test or real?
There's 2 different concepts, Test mode and Live mode, the latter being able to process real payments. You specify it by using your Stripe account secret keys.
But also there's a
- Local CLI webhook secret (
stripe listen ...), which you can find in CLI logs - Regular webhook secret, and you can find on the Dashboard -> Developers -> Webhooks
yup i know, but the whole problem now is that i can't test it locally. So i want to test it well.. non local.
Then you need to use the webhook secret from your Stripe Dashboard.
i suppose it's this key right
in that case dissapointing news, still the same error.
I am using my own stripe test key
but a live webhook key
or is that not possible?
please let me know
Which error?
i currently have this config going on.
It's not local, i use a test stripe key and a live webhook key
That doesn't make any sense. What's an example evt_xxx that is erroring?
wdym?
The ID of an Event object that your webhook is trying to handle that throws the errors
Can you please paste that ID
Taking a look
Ok, the whsec_xxx you're using in your code. Where did you find that?
i got this webhook key from the developr portal though
On the webhook page there's a button that says signing secret or something, you need to expose it
Will be formatted like whsec_xxx
NOT we_xxx – that's the ID of the webhook endpoint (irrelevant really)
there aint no way
Did that fix it?
still the same thing
i just don't know what going wrong
always this message
StripeSignatureVerificationError: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
Ok, which URL did you copy the whsec_xxx from?
No, the Dashboard URL from your browsers address bar
Paste it here
Your secret ends in 8OGYv yes?
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
this?
Well a bit more specific, I'm guess it's: https://dashboard.stripe.com/test/webhooks/we_1Oo1BTDJ6bpDzZzv2EJgxfJe
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
my webhook secret? No.
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Then you're using the wrtong one
That is the live webhook endpoint for your URL. You're trying to process test event(s) so it uses the test webhook for the same URL: https://dashboard.stripe.com/test/webhooks/we_1Oo1BTDJ6bpDzZzv2EJgxfJe
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Copy the signing secret from there
should i disable testmode?
You don't disable test mode. The toggle on the Dashbaord just alternates what dataset you're viewing
The evt_xxx ID you shaed with me is from test mode: https://dashboard.stripe.com/test/events/evt_3Oo39oDJ6bpDzZzv1GhGO94V
That means it was fired in test mode as it was created by an action/request using your test keys
Therefore that event will only be sent to test mode webhooks, like https://dashboard.stripe.com/test/webhooks/we_1Oo1BTDJ6bpDzZzv2EJgxfJe
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
If you're processing test mode events sent to test mode endpoints, then your code needs to use the signing secret (whsec_xxx) for the correct endpoint
You can have multiple webhooks that use the same URL, as you do
Ok, what is it?
this metadata seems to be undefined:
const metadata = request.body.data.object.metadata;
const cart = JSON.parse(metadata.cart);
this is how i set it:
const session = await stripe.checkout.sessions.create({
line_items: items,
mode: "payment",
success_url: "https://tsfeerhuysch.nl/success.html",
cancel_url: "https://tsfeerhuysch.nl/failed.html",
metadata: {
cart: JSON.stringify(apiCart),
},
});```
i tried to add some metdata to the session create so that i could access that data in the webhook. But not sure whether it's correct what i am doing
can i just add metadata to the sessions like that, and can i then just access it?
OK, so you're using Checkout Sessions so that top level metadata parameter is only set on the Checkout Session object and related events (like checkout.session.completed)
The recommendation is to use those events, not payment_intent.* events
If you want to use payment_intent.* events (not recommended) then you need to set the payment_intent_data[metadata] parameter instead: https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-payment_intent_data-metadata
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
i have changed it!
I will try it out now
19|koop | TypeError: Cannot read properties of undefined (reading 'object')
19|koop | at /root/site/koop.js:27:40
can't seem to find it anyways
"metadata": {
},
the metadata seems to be empty
Please paste the evt_xxx ID
we_1Oo11mDJ6bpDzZzvYfO0xgHN
i can't seem to find it
sorry it's my first time using stripe.
i am using this endpoint now
That's a live mode endpoint
You're creating your Checkout Sessions on test mode. Example checkout.session.completed event where metadata is set: https://dashboard.stripe.com/test/events/evt_1Oo4X5DJ6bpDzZzvcEv9BOpD
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
You didn't update the test mode webhook to listen for checkout.session.completed events
where can i find that wbehook
i can only see this one
I recommend deleting the live mode webhooks and forgetting about it for now. You're not using your live API keys yet so they're irrelevant
Toggle the testmode
okay i did it
also changed the webhook to this:
metdata is still not defined
const metadata = request.body.data.object.metadata;
const cart = JSON.parse(metadata.cart);
is this event a correct way of accessing it?
That error is not really helpful without full context of your code really
this is the code
where it comes from
Should be, error implies that request.body.data is undefined
The full webhook code
app.post(
"/webhook",
express.raw({ type: "application/json" }),
(request, response) => {
const stripeSignature = request.headers["stripe-signature"];
let event;
try {
const stripePayload = request.body;
event = stripe.webhooks.constructEvent(
stripePayload,
stripeSignature,
endpointSecret
);
} catch (err) {
console.log(err);
response.status(400).send(`Webhook Error: ${err.message}`);
return;
}
const metadata = request.body.data.object.metadata;
const cart = JSON.parse(metadata.cart);
if (event.type === "checkout.session.completed") {
//something here
}
trying it rn
You use the event variable you've set after the constructEvent function has resolved
i do have another small issue
{
19|koop | cookie: '7176397390',
19|koop | cart: [ { name: 'istanbul_152.5', quantity: 1 } ],
19|koop | email: 'ijsgo}qhn@op{sdrs1lot',
19|koop | name: 'sdf sdf',
19|koop | bezorging: 'Bezorgen',
19|koop | adress: 'sdf',
19|koop | straatnaam: 'sdf',
19|koop | huisnummer: '2',
19|koop | woonplaats: 'sdf',
19|koop | prijs: '€639.99'
19|koop | }
19|koop | [ { name: 'istanbul_152.5', quantity: 1 } ]
19|koop | undefined
19|koop | 7176397390
19|koop | undefined```
What's the issue?
19|koop | TypeError: Cannot read properties of undefined (reading 'length')
19|koop | at decrypt (/root/site/koop.js:130:29)```
it has to do with my parsing
Can you share your code?
ofc!
app.post(
"/webhook",
express.raw({ type: "application/json" }),
(request, response) => {
const stripeSignature = request.headers["stripe-signature"];
let event;
try {
const stripePayload = request.body;
event = stripe.webhooks.constructEvent(
stripePayload,
stripeSignature,
endpointSecret
);
} catch (err) {
console.log(err);
response.status(400).send(`Webhook Error: ${err.message}`);
return;
}
const metadata = event.data.object.metadata;
const cart = JSON.parse(metadata.cart);
console.log("cart:" + cart);
if (event.type === "checkout.session.completed") {
console.log("Payment succeeded:", event.data.object);
fetch("https://api.tsfeerhuysch.nl:4434/api/completed", {
method: "POST",
headers: {
"Content-Type": "application/json",
sessionkey: cart.cookie,
},
body: JSON.stringify(cart),
})
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.catch((error) => {
// Handle errors
console.error("There was a problem with the fetch operation:", error);
});
} else {
console.log("Payment failed:", event.data.object);
}
response.send();
}
);```
in my webhook, if it's a success it will parse the data and send it forward
i will get an image of the card data
one sec
Ok, but which part is throwing the error? I don't see a length property in that code
metadata: {
cart: '{"cookie":"7176397390","cart":[{"name":"istanbul_152.5","quantity":1}],"email":"ijsgo}qhn@op{sdrs1lot","name":"sdf sdf","bezorging":"Bezorgen","adress":"sdf","straatnaam":"sdf","huisnummer":"2","woonplaats":"sdf","prijs":"€639.99"}'```
Maybe an error at your fetch endpoint?
yeah i am getting that info rn
function decrypt(input, key) {
console.log(input);
let result = "";
for (let i = 0; i < input.length; i++) {
let unicode = input.charCodeAt(i);
let decrementer = Number(key.charAt(i % key.length));
unicode = ((unicode - 33 - decrementer + 95) % 95) + 33;
result += String.fromCharCode(unicode);
}
return result.replaceAll(`\u007f`, " ");
}```
it's at this stack here
the input seems undefined
i am probably accessing the metadata wrong?
To be clear these errors aren't specific to Stripe code or your integration, so we're kind of limited to what we can help with
yeah ofcurse, i appreciate everything you've been doing for me!!
Hard to say without seeing where you call this decrypt function
let apiCart = req.body;
console.log(apiCart);
apiCart = apiCart.cart;
console.log(apiCart);
console.log(apiCart.email);
let sessionkey = req.headers.sessionkey;
console.log(sessionkey);
const email = decrypt(apiCart.email, JSON.parse(sessionkey));```
this is in the other endpoint
somehow i am messing up how i read the metadata and how i access it
const cart = JSON.parse(metadata.cart);
if (event.type === "checkout.session.completed") {
console.log("cart hier\n" + cart);```
h
this part outputs [Object Object]
this means that i gotta parse it right?
Well it means cart is an object. Then you stringify it and pass it in the body of your fetch call you likely need to parse it again yes before passing it to decrypt
omg it finally
wroks
omg
ynnoj you are honestly the best
i have one final and last question
how can i now migrate this to live version?
As both this endpoint AND key are test?
Well you'd make the same API requests with your live keys
That would fire the related checkout.session.* events in live more and send them to your live webhook
should i move this one to live mode?
I don't know what you mean
is this webhook good for live mode?
https://dashboard.stripe.com/webhooks/we_1Oo11mDJ6bpDzZzvYfO0xgHN
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
just trying to make sure it works
Yes, that is a live mode webhook
Then you'd swithc your code to use that whsec_xxx in live mode yes
so now everything should work like before?
i see
Should do
because previosuly i copied this exact whsec
and it gave me that error we encountered
so that's why i am double checking
Yes, because you were making API requests to create Checkout Sessions with your test keys
but i guess it was because the stripe api was using test, while the webhook was the live mode
i see
If you swithc that with your live keys then it'll be fine
Yes