Closed giacomo-m closed 4 years ago
Hey Giacomo,
Thanks for reaching out. Can you share a bit more of your webhook handling code? One of the more common issues is that the payload is somehow formatted and not passed in as the raw string request body.
Also, we'd be happy to field questions like this at support.stripe.com/contact or on IRC where there are Stripe engineers available to chat during most business hours in the #stripe channel on Freenode (https://webchat.freenode.net/?channel=#stripe).
Closing due to inactivity, but feel free to reply if you're still having trouble and we'll reopen.
I am using stripe cli and want to test webhooks locally. somehow my signatures didn't get verified. I don't know what happens with it. I follow the instruction given on stripe documentation.
my header of the request is some thing like below
{ host: 'localhost:8082', 'user-agent': 'Stripe/1.0 (+https://stripe.com/docs/webhooks)', 'content-length': '3646', accept: '/; q=0.5, application/xml', 'cache-control': 'no-cache', 'content-type': 'application/json; charset=utf-8', 'stripe-signature': 't=1594120195,v1=af8a2f86ad323bc33659b3adcc09a96230bb16087ef7722c4de21fcae098e6a0,v0=af2697576d5efdd27ab3f572b974c5b87a84804a0f327b5947909d6a22343dd6', 'accept-encoding': 'gzip', ip: '::ffff:127.0.0.1' }
I got the error something like below
No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing
any idea what's going wrong with it?
stripe version 1.4.4
FYI, I am just using the sample code from below stripe link
@JD-sixberries The Stripe CLI has its own webhook secret so you need to make sure you are using that one properly. It's also important to ensure that your code or framework is not tampering with the raw data we sent you. The signature verification only works with the exact raw JSON, up to the exact new line or indentation space. Those 2 reasons are the most common reasons for this issue.
If you're still having problems after that, we recommend that you reach out to our support team: https://support.stripe.com/contact
@remi-stripe thanks for your suggestion. my code tampering the request data using overall body-parser into the JSON format. So I need to change the position of a webhooks route to the top of all other middleware into the server configuration
Thanks for following up. I'm glad to hear you were able to narrow down the issue and resolve it on your end!
@remi-stripe following this Node guide https://stripe.com/docs/payments/checkout/fulfill-orders I get exactly the same problem. Any ideas how to solve it?
@AAverin I'd recommend talking to our support team for help on this: https://support.stripe.com/contact
@JD-sixberries
I think that you have this error because your forgotten to use:
bodyParser.raw({ type: 'application/json' }),
This step is mandatory to avoid "Signature verification failures".
Simple and working example:
const webhooksStripeRouter: Router = Router();
webhooksStripeRouter.post(
'/webhooks/stripe',
bodyParser.raw({ type: 'application/json' }), // <==== don't forget this
async (req: Request, res: Response) => {
try {
// Retrieve the event by verifying the signature using the raw body and secret.
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
req.body,
req.headers['stripe-signature'],
'whsec_jtfJGfWz8YqSwCUExxxxxxxxxxxy',
);
} catch (error) {
throw new Error('Stripe webhook signature verification failed.');
}
// Extract the data from the event.
const { data, type }: { data: Stripe.Event.Data; type: string } = event;
if (type === 'payment_intent.succeeded') {
// Cast the event into a PaymentIntent to make use of the types.
const paymentIntent: Stripe.PaymentIntent = data.object as Stripe.PaymentIntent;
// Funds have been captured
// Fulfill any orders, e-mail receipts, etc
// To cancel the payment after capture you will need to issue a Refund (https://stripe.com/docs/api/refunds).
console.log(`🔔 Webhook received: ${paymentIntent.object} ${paymentIntent.status}!`);
console.log('💰 Payment captured!');
} else if (type === 'payment_intent.payment_failed') {
// Cast the event into a PaymentIntent to make use of the types.
const pi: Stripe.PaymentIntent = data.object as Stripe.PaymentIntent;
console.log(`🔔 Webhook received: ${pi.object} ${pi.status}!`);
console.log('❌ Payment failed.');
}
res.sendStatus(200);
} catch (error) {
console.debug(error);
}
},
);
@JD-sixberries
I think that you have this error because your forgotten to use:
bodyParser.raw({ type: 'application/json' }),
This step is mandatory to avoid "Signature verification failures".
Simple and working example:
const webhooksStripeRouter: Router = Router(); webhooksStripeRouter.post( '/webhooks/stripe', bodyParser.raw({ type: 'application/json' }), // <==== don't forget this async (req: Request, res: Response) => { try { // Retrieve the event by verifying the signature using the raw body and secret. let event: Stripe.Event; try { event = stripe.webhooks.constructEvent( req.body, req.headers['stripe-signature'], 'whsec_jtfJGfWz8YqSwCUExxxxxxxxxxxy', ); } catch (error) { throw new Error('Stripe webhook signature verification failed.'); } // Extract the data from the event. const { data, type }: { data: Stripe.Event.Data; type: string } = event; if (type === 'payment_intent.succeeded') { // Cast the event into a PaymentIntent to make use of the types. const paymentIntent: Stripe.PaymentIntent = data.object as Stripe.PaymentIntent; // Funds have been captured // Fulfill any orders, e-mail receipts, etc // To cancel the payment after capture you will need to issue a Refund (https://stripe.com/docs/api/refunds). console.log(`🔔 Webhook received: ${paymentIntent.object} ${paymentIntent.status}!`); console.log('💰 Payment captured!'); } else if (type === 'payment_intent.payment_failed') { // Cast the event into a PaymentIntent to make use of the types. const pi: Stripe.PaymentIntent = data.object as Stripe.PaymentIntent; console.log(`🔔 Webhook received: ${pi.object} ${pi.status}!`); console.log('❌ Payment failed.'); } res.sendStatus(200); } catch (error) { console.debug(error); } }, );
Thanks @rimiti I get the help when I reported or facing this issue. actually I convert my request data into the JSON which cause the issue otherwise it working as expected. So basically that was my bad during implementation
Im using nestjs and was using @Body
which parses the body, I tried being smart by turning it back into a string using JSON.stringify but this messed it up. So opted to using the raw body instead and it works!
Hi, i'm using Stripe CLI for testing my webhook.
event = Webhook.constructEvent(payload, <Stripe-Signature header>, <Stripe CLI signing secret>);
always returns an exception "No signatures found matching the expected signature for payload".Stripe CLI signing secret:
whsec_2QF92N94RwqD5M6t553xec5ce3NGgfKs
Stripe-Signature header:
t=1576858212,v1=63dbd81dd42f4b5406451e4add0b89357a62598deba8e1978e53d005487927a6,v0=3016f803483615a7f75716ca92c404f5e550eab968640a85c738f31c42109770
Payload: { "id": "evt_1Fro3MEErckdb3enb7aSN8js", "object": "event", "api_version": "2019-12-03", "created": 1576858211, "data": { "object": { "id": "pi_1Fro3KEErckdb3enotYuEhG1", "object": "payment_intent", "amount": 2000, "amount_capturable": 0, "amount_received": 2000, "application": null, "application_fee_amount": null, "canceled_at": null, "cancellation_reason": null, "capture_method": "automatic", "charges": { "object": "list", "data": [ { "id": "ch_1Fro3LEErckdb3ene1m27XhJ", "object": "charge", "amount": 2000, "amount_refunded": 0, "application": null, "application_fee": null, "application_fee_amount": null, "balance_transaction": "txn_1Fro3LEErckdb3ene7NN6V5C", "billing_details": { "address": { "city": null, "country": null, "line1": null, "line2": null, "postal_code": null, "state": null }, "email": null, "name": null, "phone": null }, "captured": true, "created": 1576858211, "currency": "usd", "customer": null, "description": "(created by Stripe CLI)", "destination": null, "dispute": null, "disputed": false, "failure_code": null, "failure_message": null, "fraud_details": { }, "invoice": null, "livemode": false, "metadata": { }, "on_behalf_of": null, "order": null, "outcome": { "network_status": "approved_by_network", "reason": null, "risk_level": "normal", "risk_score": 22, "seller_message": "Payment complete.", "type": "authorized" }, "paid": true, "payment_intent": "pi_1Fro3KEErckdb3enotYuEhG1", "payment_method": "pm_1Fro3KEErckdb3enJWQW6BYP", "payment_method_details": { "card": { "brand": "visa", "checks": { "address_line1_check": null, "address_postal_code_check": null, "cvc_check": null }, "country": "US", "exp_month": 12, "exp_year": 2020, "fingerprint": "RhCup5EEbm2AICiC", "funding": "credit", "installments": null, "last4": "4242", "network": "visa", "three_d_secure": null, "wallet": null }, "type": "card" }, "receipt_email": null, "receipt_number": null, "receipt_url": "https://pay.stripe.com/receipts/acct_1CaOCdEErckdb3en/ch_1Fro3LEErckdb3ene1m27XhJ/rcpt_GObFdv7k1cm1CvM4rAu2RGn6kTkYvtl", "refunded": false, "refunds": { "object": "list", "data": [
}, "livemode": false, "pending_webhooks": 2, "request": { "id": "req_QxV95RJcUkjLaJ", "idempotency_key": null }, "type": "payment_intent.succeeded" }
API version: 2019-12-03
Can you help me?
Thanks. Giacomo