#IVOBOT
1 messages ยท Page 1 of 1 (latest)
Hi there!
Can you clarify when/where you get errors? Is it when you make an API request to Stripe? If so can you share the request ID (req_xxx)?
"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"
The code I use:
const sig = request.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
} catch (err) {
console.log(err.message)
response.status(400).send(`Webhook Error: ${err.message}`);
return;
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntentSucceeded = event.data.object;
// Then define and call a function to handle the event payment_intent.succeeded
break;
// ... handle other event types
default:
console.log(`Unhandled event type ${event.type}`);
}
// Return a 200 response to acknowledge receipt of the event
response.send();
});```
So you are getting this error trying to verify the signature of a webhook event?
Yes
Also received a lot of 400 responses on the Stripe Dashboard (received events)
This is a common error when using Node.js
Oh
Have you tried looking into the solutions mentionned here: https://github.com/stripe/stripe-node/issues/341
I think I may've tried it
So what's essentially the solution if it's so common?
The solution is to make sure you are using the raw body. How to do that depend on many factors. That's why I recommend checking the link above.
Okay
But I don't really know how to execute it this way. I mean my app is really simple, so it's main purpose is getting payments and receiving this webhook.
๐ taking over for my colleague. Let me know if there's any follow-up Qs I can answer!
Hm?
This solution doesn't work, still getting 400 responses, although payment goes through.
eg
evt_1Mo2ydLqyuD0FDRd9Uv3ta8K
are you using stripe listen --forward-to ...?
emm, I am using the official Stripe vs code extension based on Stripe CLI
listen --forward-to http://localhost:4242/webhook --forward-connect-to http://localhost:4242/webhook
But yes
as i can see on the cli
it is the --forward-connect-to
please remove the --forward-connect-to
okay
this is important if you're listening to the Connect Account events
which stripe-cli version you have?
i suppose the newest, because I downloaded it yesterday via homebrew
Still:
2023-03-21 12:26:43 --> checkout.session.completed [evt_1Mo3KxLqyuD0FDRdoUO1mrVm]
2023-03-21 12:26:43 <-- [400] POST http://localhost:4242/webhook [evt_1Mo3KxLqyuD0FDRdoUO1mrVm]
And
No webhook payload was provided.
No webhook payload was provided.
No webhook payload was provided.
No webhook payload was provided.
on the "node"
would you mind adding a console.log(request.body)
before the event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret)
okay
{
id: 'evt_1Mo3YaLqyuD0FDRdU7XLCBu8',
object: 'event',
api_version: '2022-08-01',
created: 1679398848,
data: {
object: {
id: 'cs_test_a1GJrfFtLZTgigvgRrToTLGdCIp0O1Nh9fOjgm9fB4kPFMNyllY74Zu2uz',
object: 'checkout.session',
after_expiration: null,
allow_promotion_codes: null,
amount_subtotal: 3999,
amount_total: 3999,
automatic_tax: [Object],
billing_address_collection: null,
cancel_url: '',
client_reference_id: null,
consent: null,
consent_collection: null,
created: 1679398820,
currency: 'usd',
custom_fields: [],
custom_text: [Object],
customer: null,
customer_creation: 'if_required',
customer_details: [Object],
customer_email: null,
expires_at: 1679485220,
invoice: null,
invoice_creation: [Object],
livemode: false,
locale: null,
metadata: {},
mode: 'payment',
payment_intent: 'pi_3Mo3YLLqyuD0FDRd0F4AUrni',
payment_link: null,
payment_method_collection: 'always',
payment_method_options: {},
payment_method_types: [Array],
payment_status: 'paid',
phone_number_collection: [Object],
recovered_from: null,
setup_intent: null,
shipping_address_collection: null,
shipping_cost: null,
shipping_details: null,
shipping_options: [],
status: 'complete',
submit_type: null,
subscription: null,
success_url: '',
total_details: [Object],
url: null
}
},
livemode: false,
pending_webhooks: 2,
request: { id: null, idempotency_key: null },
type: 'checkout.session.completed'
}
No webhook payload was provided.
The No webhook payload was provided. implies that your endpointSecret is wrong: https://github.com/stripe/stripe-node/blob/master/test/Webhook.spec.ts#L109
Which whsec_xxx are you using?
The one from the CLI?
yes
Double checked it
still the same 400 response
I can't even see endpointSecret var defined in your code
I only sent you a webhook from my code but endpointSecret is defined as a string of a text like this: "whsec_xxx"
And that whsec_xxx is the one the CLI spits out when you use stripe listen?
yes
Not sure unfortunately. Maybe your CLI is signed into a different account?
No, because I do receive the same responses on the dashboard
Well the CLI doesn't log responses in the Dashboard
Which evt_xxx are you looking at?
The CLI doesn't log any webhook errors in your Dashboard. They'll all appear as successful
Hi ๐ apologies for the delay, taking over for my teammates.
Looks like there is quite a bit of context in this thread and the focus has moved around. Would you mind summarizing for me the current state of your concern/problem?
Well, I'm not super fluent at it, but there's some sort of an issue with my webhook, because of it's body (which is undefined for some reason, but then it returns the correct state of checkout.session) or a key (which we excluded I suppose). I am constantly getting results 400 or 404 upon the arrival of the response from webhook.
And the main thing is that the code I am using is straight from the Stripe dashboard, so there should not be any issue, yet I can't do anything on my server precisely and only after the payment has succeeded (because the webhooks doesn't seem to work properly).
Webhooks do not block payments, nor are they expected to.
The main issue is "No webhook payload was provided." I think. As said before, there might be a problem with formatting of the body, but it's the code from the dashboard and I am not that fluent with webhooks
Correct, but they are the only way to execute some code only when the payment was successful (as the Stripe docs and support said, you should not implement it via success_url).
Correct, webhooks are the preferred route for triggering after payment actions to avoid running into incomplete flows if a customer suddenly loses connection after triggering a payment.
Where are you seeing the No webhook payload was provided message being raised?
During this debugging with people before you we added some console.logs to the try catch
So
here:
try {
console.log(request.body)
event = stripe.webhooks.constructEvent(request.body, sig, process.env.STRIPE_WEBHOOK_SECRET);
} catch (err) {
console.log(err.message)
response.status(400).send(`Webhook Error: ${err.message}`);
return;
}
So it's being thrown by that log in the catch block? Can you share your larger code snippet? I see you're referencing request.rawBody in your constructEvent call, but I don't recall seeing that defined in your previous code that you shared.
Yeah, a small mistake. It was supposed to be "body". Still doesn't work tho.
Same error or different one?
Same one
I mean response 400
2023-03-21 14:48:48 --> checkout.session.completed [evt_1Mo5YSLqyuD0FDRd7K3s3DlF]
2023-03-21 14:48:48 <-- [400] POST http://localhost:4242/webhook [evt_1Mo5YSLqyuD0FDRd7K3s3DlF]
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
Node.js library for the Stripe API. . Contribute to stripe/stripe-node development by creating an account on GitHub.
Okay, so a different error.
Right, but there's still something with the body, as I assume the key is correct (as it is the same as the one from CLI and Dashboard).
Try adding this to set up bodyParser to give you both the parsed body and the raw one:
verify: (req, res, buf) => {
req.rawBody = buf
}
})); ```
Then can you try referencing `request.rawBody` as you had before?
okay
require('dotenv').config();
const express = require('express');
const app = express();
const cors = require('cors');
const { createClient } = require('@supabase/supabase-js');
const {bodyParser} = require("body-parser")
app.use(express.json());
app.use(cors({
origin: 'http://localhost:3000',
}));
app.use(bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf
}
}));
const stripe = require('stripe')(process.env.STRIPE_PRIVATE_KEY);
Is this the correct place?
app.use(bodyParser.json({
^
TypeError: Cannot read properties of undefined (reading 'json')
Something wrong
Ah, you had:
app.use(express.json());
which I believe would have parsed all your request bodies to JSON.
Do you need the JSON parsing for another part of your process? If not I'd suggest removing what I suggested, removing the line I referenced above, and then try running it again.
ou
so this might've been an issue
Yeah, but I fetched product from the frontend as an object (added handler to the post)
Yay
I think
something is fixed
What does this handler mean, btw? And why it acts so strange?
Can you elaborate?
Oh wait, theres still some issue
2023-03-21 15:05:50 <-- [200] POST http://localhost:4242/webhook [evt_3Mo5oiLqyuD0FDRd0TyrBL03]
2023-03-21 15:05:50 --> charge.succeeded [evt_3Mo5oiLqyuD0FDRd0T6C4zXS]
2023-03-21 15:05:50 <-- [200] POST http://localhost:4242/webhook [evt_3Mo5oiLqyuD0FDRd0T6C4zXS]
2023-03-21 15:05:51 --> checkout.session.completed [evt_1Mo5oxLqyuD0FDRdEjtj3b3j]
2023-03-21 15:05:51 <-- [200] POST http://localhost:4242/webhook [evt_1Mo5oxLqyuD0FDRdEjtj3b3j]
2023-03-21 15:08:21 --> payment_intent.requires_action [evt_3Mo5rMLqyuD0FDRd1YtUsca7]
2023-03-21 15:08:21 <-- [200] POST http://localhost:4242/webhook [evt_3Mo5rMLqyuD0FDRd1YtUsca7]
2023-03-21 15:08:21 --> payment_intent.created [evt_3Mo5rMLqyuD0FDRd1Waq9OQs]
2023-03-21 15:08:21 <-- [200] POST http://localhost:4242/webhook [evt_3Mo5rMLqyuD0FDRd1Waq9OQs]
2023-03-21 15:08:33 --> payment_intent.succeeded [evt_3Mo5rMLqyuD0FDRd1euIdAvH]
2023-03-21 15:08:33 <-- [500] POST http://localhost:4242/webhook [evt_3Mo5rMLqyuD0FDRd1euIdAvH]
2023-03-21 15:08:33 --> charge.succeeded [evt_3Mo5rMLqyuD0FDRd1SbRVY6D]
2023-03-21 15:08:33 <-- [200] POST http://localhost:4242/webhook [evt_3Mo5rMLqyuD0FDRd1SbRVY6D]
2023-03-21 15:08:33 --> checkout.session.completed [evt_1Mo5rZLqyuD0FDRdSQzHKoMC]
2023-03-21 15:08:33 <-- [200] POST http://localhost:4242/webhook [evt_1Mo5rZLqyuD0FDRdSQzHKoMC]
the only one event i care about (succeeded) is 500
ugh
That 500 indicates your code crashed while trying to handle the Event that it received, you'll need to debug the code that is handling your Events to determine why.
You'll need to get to the higher-order object that contains Product references. Looks like you're using Checkout Sessions, so that is probably what you're looking for.
You'll either want to retrieve the Checkout Session that is associated with the Payment Intent in the Event you're handling (if you continue to work with Payment Intent Events), or you pivot to listening to Checkout Session events such as checkout.session.completed.
Okay, but I do not have all the product info inside the Checkout Session. Can I add some additional JSON Object to the Checkout Session on its creation?
Oh, so when you say Product info, you aren't referring to Product objects that you're using?
https://stripe.com/docs/api/products
If so, you're probably want to leverage metadata:
https://stripe.com/docs/api/metadata
Or should I just ask: what is the preferable way of accessing the bought product after the payment succeeded
Yes
Because I need the user id from my database (which is acquired on creation of checkout session) in order to add the new product to his records after the payment
If you aren't using Products and referencing those objects, then you'll need to provide your own product information/context. The best way to do that is via metadata which lets you store key-value pair data on Stripe objects, that you can then reference later.
Okay, maybe let's clear things up. The user clicks "buy" and gives my backend his ID, product ID and some other parameters. Then the product ID is used by checkout session in order to process payment (first it gets the product data from my DB and then this data is added to the checkout session) and then after successful payment I want to pushItem() to my DB (which should be done via webhooks), and the pushItem needs user Id, product Id and the other parameters from the first step of this whole process.
How can I retrieve these parameters in the most effective way possible? I don't necessarily want stripe to have it all on their server as it may be a lot of data or data in a unfavorable way (JSON Object). What approach should I choose?
Or what do you propose?