#IVOBOT

1 messages ยท Page 1 of 1 (latest)

dusk bronzeBOT
safe locust
#

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)?

snow hull
#

"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"

GitHub

Node.js library for the Stripe API. . Contribute to stripe/stripe-node development by creating an account on GitHub.

#

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();
  });```
safe locust
#

So you are getting this error trying to verify the signature of a webhook event?

snow hull
#

Yes

dusk bronzeBOT
snow hull
#

Also received a lot of 400 responses on the Stripe Dashboard (received events)

safe locust
#

This is a common error when using Node.js

snow hull
#

Oh

safe locust
snow hull
#

I think I may've tried it

snow hull
safe locust
#

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.

snow hull
#

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.

naive parcel
#

๐Ÿ‘‹ taking over for my colleague. Let me know if there's any follow-up Qs I can answer!

snow hull
#

Hm?

naive parcel
#

sorry I thought my colleague already answered your question

#

let me catch up

snow hull
#

This solution doesn't work, still getting 400 responses, although payment goes through.

naive parcel
#

would you mind sharing any event ID?

#

evt_xxx

snow hull
#

eg

evt_1Mo2ydLqyuD0FDRd9Uv3ta8K

naive parcel
#

are you using stripe listen --forward-to ...?

snow hull
#

emm, I am using the official Stripe vs code extension based on Stripe CLI

naive parcel
#

which one?

#

how are you testing your webhook?

snow hull
#

But yes

#

as i can see on the cli

#

it is the --forward-connect-to

naive parcel
#

please remove the --forward-connect-to

snow hull
#

okay

naive parcel
#

this is important if you're listening to the Connect Account events

#

which stripe-cli version you have?

snow hull
#

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"

naive parcel
#

would you mind adding a console.log(request.body)

#

before the event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret)

snow hull
#

okay

dusk bronzeBOT
snow hull
# naive parcel would you mind adding a `console.log(request.body)`

{
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.

steady nebula
#

Which whsec_xxx are you using?

#

The one from the CLI?

snow hull
#

Double checked it

#

still the same 400 response

steady nebula
#

I can't even see endpointSecret var defined in your code

snow hull
#

I only sent you a webhook from my code but endpointSecret is defined as a string of a text like this: "whsec_xxx"

steady nebula
#

And that whsec_xxx is the one the CLI spits out when you use stripe listen?

snow hull
#

yes

steady nebula
#

Not sure unfortunately. Maybe your CLI is signed into a different account?

snow hull
#

No, because I do receive the same responses on the dashboard

steady nebula
#

Well the CLI doesn't log responses in the Dashboard

snow hull
#

I mean I think it is the according 400 response

#

Bc of the same event Id etc.

steady nebula
#

Which evt_xxx are you looking at?

#

The CLI doesn't log any webhook errors in your Dashboard. They'll all appear as successful

snow hull
#

Something like this

brazen raptor
#

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?

snow hull
#

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).

brazen raptor
#

Webhooks do not block payments, nor are they expected to.

snow hull
#

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

snow hull
brazen raptor
#

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?

snow hull
#

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;
    }
brazen raptor
#

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.

snow hull
#

Yeah, a small mistake. It was supposed to be "body". Still doesn't work tho.

brazen raptor
#

Same error or different one?

snow hull
#

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

GitHub

Node.js library for the Stripe API. . Contribute to stripe/stripe-node development by creating an account on GitHub.

brazen raptor
#

Okay, so a different error.

snow hull
#

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).

brazen raptor
#

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?
snow hull
#

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

brazen raptor
#

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.

snow hull
#

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?

brazen raptor
#

Can you elaborate?

snow hull
#

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

brazen raptor
#

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.

snow hull
#

okay

#

how can I transfer product parameters from payment handling to the webhook?

brazen raptor
#

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.

snow hull
#

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?

brazen raptor
snow hull
#

Or should I just ask: what is the preferable way of accessing the bought product after the payment succeeded

snow hull
#

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

brazen raptor
#

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.

snow hull
#

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?