#sagar_error

1 messages ยท Page 1 of 1 (latest)

woeful peakBOT
#

๐Ÿ‘‹ 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/1301136741700210690

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

quiet bluff
#

hi! what does your code look like for handling the webhook? What's an example evt_xxx ID where it happens?

candid crater
#

hi @quiet bluff
i am getting the error while using this function
stripe.webhooks.signature.verifyHeader()
this started from today morning itself and production app is also facing the same error even without pushing the code to production form last 5 months

type: 'StripeSignatureVerificationError',
raw: {
message: 'No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? \n' +
'\n' +
'Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing\n'
},

quiet bluff
#

can you share the complete code of the endpoint and an example evt_xxx?

candid crater
quiet bluff
#

hmm oh yeah that thing

#

can you share the complete code you wrote? and add logs to log the values of the payload and sig you pass to verifyHeader and share those exact values?

candid crater
#

let Stripe = require('stripe')
require('dotenv').config()
const stripe = new Stripe(process.env.STRIPE_API_KEY, {
apiVersion: '2024-04-10',
})

const verifyStripeSignature = async (req, res, next) => {
try {
const sig = req.headers['stripe-signature'];
const payload = JSON.stringify({
user_id: req.body.user_id,
account_id: req.body.account_id
})
// let signature = true
let signature = stripe.webhooks.signature.verifyHeader(payload, sig, process.env.STRIPE_SECRET_KEY)

if (!signature) throw message.NOT_FROM_STRIPE
next()
} catch (error) {
  console.log(error)
  return next(error.message)
}

}

here is the code

quiet bluff
#

FWIW:
process.env.STRIPE_SECRET_KEY
that's not meant to be an API key(sk_xxx), it's a secret you get from the Apps settings page; if that's the issue.

candid crater
#

we got the secret form the app setting itself (absec_xxxx) one you mean?

quiet bluff
#

yes

candid crater
#

we are using that only
but still facing the same.

quiet bluff
#

and add logs to log the values of the payload and sig you pass to verifyHeader and share those exact values?

candid crater
#

sure sending

#

Payload : {"user_id":"usr_PGYv2XA6JcvblF","account_id":"acct_1PJWO9DMcUa7nI7M"}
Signature : t=1730286665,v1=f0fa51331eb498b20f05cdd68536406ed5ff2c3ffa788c3158d5d34a63299558

#

StripeSignatureVerificationError: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?

quiet bluff
#

hmm, thinking

#

on the frontend are you passing the payload when you create the signature?

await fetchStripeSignature(payload)
#

though I'm not sure this actually helps, since we do say By default, Stripe apps use user_id and account_id to generate the signature string. so presumably your signature string is correct

#

I really don't know sorry. Maybe try copying the Apps secret again from your Dashboard and hard-coding it directly in your code and restart the server. And try installing the App on a fresh account too.

pulsar snow
#

Can you share your code that makes the request from your app to the backend?

candid crater
#

sure
import { fetchStripeSignature } from "@stripe/ui-extension-sdk/utils";

let signaturePayload = {};
signaturePayload.user_id = userContext?.id;
signaturePayload.account_id = userContext?.account.id;

let fetch2 = await fetch(`${environment.constants.API_BASE}/user`, {
  method: 'POST',
  headers: {
    'Stripe-Signature': await fetchStripeSignature(),
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    ...signaturePayload,
    roles: userContext.roles
  }),
});
const res = await fetch2.json();
#

hi @pulsar snow waiting for your response

pulsar snow
#

Can you change the body parameter so the signaturePayload hash is spread after the roles key?

body: JSON.stringify({
  roles: userContext.roles,
  ...signaturePayload
})
#

You say this code has been working fine? That would imply to me the app secret has changed

candid crater
#

let fetch2 = await fetch(${environment.constants.API_BASE}/user, {
method: 'POST',
headers: {
'Stripe-Signature': await fetchStripeSignature(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
roles: userContext.roles,
...signaturePayload,
}),
});
const res = await fetch2.json();

candid crater
#

type: 'StripeSignatureVerificationError',
raw: {
message: 'No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? \n' +

pulsar snow
#

Aha, I think it's because you're stringifying the JSON before you pass it to verifyHeader:

const payload = JSON.stringify({
      user_id: req.body.user_id,
      account_id: req.body.account_id
    })

You want to keep that as an object, so something like this:

const payload = {
  user_id: req.body.user_id,
  account_id: req.body.account_id
}
candid crater
#

all of these approaches work the same way in JavaScript. Using JSON.stringify() converts an object to a JSON string, whereas keeping it as an object (without JSON.stringify()) preserves it in its original format. Both methods depend on whether you need the data as a JSON string or as an object for further manipulation.

#

all works the same

pulsar snow
#

Yeah exactly. The verifyHeader expects the request body the endpoint receives, not a malformed string

#

Please try

candid crater
#

i tried that as well although
thing mentioned in the docs doesn't match what you are saying

pulsar snow
#

You're looking at the wrong part. Yes, your fetch call inside your app you stringifies the payload โ€“ that is required. But you're also passing a string to verifyHeader in your backend, based on this: #1301136741700210690 message

#

Remove the JSON.stringify there

candid crater
#

here is the new rectified code
const verifyStripeSignature = async (req, res, next) => {
try {
const sig = req.headers['stripe-signature'];
const payload = {
user_id: req.body.user_id,
account_id: req.body.account_id
}
// let signature = true
console.log('Payload :', payload)
console.log('Signature :', sig)

let signature = stripe.webhooks.signature.verifyHeader(payload, sig, process.env.STRIPE_SECRET_KEY)

if (!signature) throw message.NOT_FROM_STRIPE
next()
} catch (error) {
  console.log(error)
  return next(error.message)
}

}

#

still the issue persist

pulsar snow
#

Is process.env.STRIPE_SECRET_KEY actually set here? Also, remove the console.logs

candid crater
#

STRIPE_SECRET_KEY is the (absec_xxxx) one

#

i will remove once the error is resolved

pulsar snow
#

Well the console.log can malform payload so it may be problematic. Please try and remove it