#costantino-webhook-connect
1 messages ยท Page 1 of 1 (latest)
Can you also check that sig_header is properly populated?
The other thing that can typically cause this is the payload being slightly manipulated. Some frameworks helpfully try to do some parsing of the request body before your endpoint function runs, but that messes up the Stripe signature calculations. So you need to make sure the raw body is getting passed in to that construct_event function
Hi @worthy belfry, and thanks or the reply. I checked the sig_header and it so populated: "t=1695724160,v1=6af26656a8d7323b3203076c72c94e0381da04c0f30e17e4ee58d3f15b8bde62,v0=918f1e580994bf0580d2f780ecccd0604cd02a9a29fdfb342094841e8702b965"
Regarding the manipulation of the request_body, can i have an example of the request body that construct_event function expects?
Unfortunately i can't give one to you like that, the signature is calculated off of your specific secret and payload
Definitely one of the things that makes this part tough to debug unfortunately
Oh wait I see what is happening
So the webhook endpoint that you provided has a different secret than whatever the Stripe CLI gave you when you started the local listener
If you go to the page for we_1NlWdTF6BC6KsJ4hgPZXFmbg on your dashboard, you can get its webhook secret and try that with the construct_event function
You mean this wh secret, right?
Exactly
I checked again, and the secret i pass to construct_event function is the same
Can you try using request.body instead of request.data? I am seeing that that may be the proper way to access the raw request body in Django
I tried.. but nothing changes..๐ฉ
The request.body is the following:
b'{\n "object": {\n "id": "pi_3NuWoPF6BC6KsJ4h0dbSHmr8",\n "object": "payment_intent",\n "amount": 2000,\n "amount_capturable": 2000,\n "amount_details": {\n "tip": {\n }\n },\n "amount_received": 0,\n "application": null,\n "application_fee_amount": null,\n "automatic_payment_methods": null,\n "canceled_at": null,\n "cancellation_reason": null,\n "capture_method": "manual",\n "client_secret": "pi_3NuWoPF6BC6KsJ4h0dbSHmr8_secret_yt70Y6auQj1By8QAYTlJek4oO",\n "confirmation_method": "manual",\n "created": 1695717609,\n "currency": "usd",\n "customer": null,\n "description": "(created by Stripe CLI)",\n "invoice": null,\n "last_payment_error": null,\n "latest_charge": "ch_3NuWoPF6BC6KsJ4h0YVe2Kw3",\n "livemode": false,\n "metadata": {\n },\n "next_action": null,\n "on_behalf_of": null,\n "payment_method": "pm_1NuWoPF6BC6KsJ4hXyW7nSI0",\n "payment_method_configuration_details": null,\n "payment_method_options": {\n "card": {\n "installments": null,\n "mandate_options": null,\n "network": null,\n "request_three_d_secure": "automatic"\n }\n },\n "payment_method_types": [\n "card"\n ],\n "processing": null,\n "receipt_email": null,\n "review": null,\n "setup_future_usage": null,\n "shipping": null,\n "source": null,\n "statement_descriptor": null,\n "statement_descriptor_suffix": null,\n "status": "requires_capture",\n "transfer_data": null,\n "transfer_group": null\n }\n}'
I think that body should have an event ID in it (evt_1234)
Checking in my code. It almost looks like your code is working with a subset of the body rather than the whole thing though I'm not sure how that could happen with the code provided
Yes thanks @worthy belfry. I don't know what to do, I'm desperate
Yep, definitely looks like some stuff is being left out. Can you send me the whole python function that your code fame from?
sig_header = request.headers['STRIPE_SIGNATURE']
wh_secretkey = "whsec***"
event = stripe.Webhook.construct_event(payload, sig_header, wh_secret_key)```
Also are you trying to listen for the payment_intent.created or payment_intent.amount_capturable_updated event on this intent?
For sure, here the code:
I'm trying to listen the payment_intent.amount_capturable_updated (this one), the 'payment_intent.succeeded' and 'account.update'
What does your get_webhook_secret_key function do here?
it takes the ws_secret for that webhook from my settings file
i checked and the wh_secret_key is correct. i also tried to set the wh_secret_key directly, but nothing changes..
Is there anything in your setup that may be manipulating the request body that we are sending you?
That intent should have a larger body around with with event data https://stripe.com/docs/api/events/object
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
It is in our logs for what we sent you for this event as well https://dashboard.stripe.com/test/events/evt_3NuWoPF6BC6KsJ4h0f7hZJgY
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Oh right, because the body that we sent you has the info that you provided under "data"
No, in Django the body request are immutable. The body request i receive is that:
{
"object":{
"id":"pi_3NuWoPF6BC6KsJ4h0dbSHmr8",
"object":"payment_intent",
"amount":2000,
"amount_capturable":2000,
"amount_details":{
"tip":{
}
},
"amount_received":0,
"application":"None",
"application_fee_amount":"None",
"automatic_payment_methods":"None",
"canceled_at":"None",
"cancellation_reason":"None",
"capture_method":"manual",
"client_secret":"pi_3NuWoPF6BC6KsJ4h0dbSHmr8_secret_yt70Y6auQj1By8QAYTlJek4oO",
"confirmation_method":"manual",
"created":1695717609,
"currency":"usd",
"customer":"None",
"description":"(created by Stripe CLI)",
"invoice":"None",
"last_payment_error":"None",
"latest_charge":"ch_3NuWoPF6BC6KsJ4h0YVe2Kw3",
"livemode":false,
"metadata":{
},
"next_action":"None",
"on_behalf_of":"None",
"payment_method":"pm_1NuWoPF6BC6KsJ4hXyW7nSI0",
"payment_method_configuration_details":"None",
"payment_method_options":{
"card":{
"installments":"None",
"mandate_options":"None",
"network":"None",
"request_three_d_secure":"automatic"
}
},
"payment_method_types":[
"card"
],
"processing":"None",
"receipt_email":"None",
"review":"None",
"setup_future_usage":"None",
"shipping":"None",
"source":"None",
"statement_descriptor":"None",
"statement_descriptor_suffix":"None",
"status":"requires_capture",
"transfer_data":"None",
"transfer_group":"None"
}
}
Right, but that is only part of the body (the part we label "data" in the json)
You need to provide the whole body
oh ok. let me check... i'll try to give you the whole body i receive
here the whole request.body i receive:
{'id': 'evt_3NuWoPF6BC6KsJ4h0f7hZJgY', 'object': 'event', 'api_version': '2022-11-15', 'created': 1695717610, 'data': {'object': {'id': 'pi_3NuWoPF6BC6KsJ4h0dbSHmr8', 'object': 'payment_intent', 'amount': 2000, 'amount_capturable': 2000, 'amount_details': {'tip': {}}, 'amount_received': 0, 'application': None, 'application_fee_amount': None, 'automatic_payment_methods': None, 'canceled_at': None, 'cancellation_reason': None, 'capture_method': 'manual', 'client_secret': 'pi_3NuWoPF6BC6KsJ4h0dbSHmr8_secret_yt70Y6auQj1By8QAYTlJek4oO', 'confirmation_method': 'manual', 'created': 1695717609, 'currency': 'usd', 'customer': None, 'description': '(created by Stripe CLI)', 'invoice': None, 'last_payment_error': None, 'latest_charge': 'ch_3NuWoPF6BC6KsJ4h0YVe2Kw3', 'livemode': False, 'metadata': {}, 'next_action': None, 'on_behalf_of': None, 'payment_method': 'pm_1NuWoPF6BC6KsJ4hXyW7nSI0', 'payment_method_configuration_details': None, 'payment_method_options': {'card': {'installments': None, 'mandate_options': None, 'network': None, 'request_three_d_secure': 'automatic'}}, 'payment_method_types': ['card'], 'processing': None, 'receipt_email': None, 'review': None, 'setup_future_usage': None, 'shipping': None, 'source': None, 'statement_descriptor': None, 'statement_descriptor_suffix': None, 'status': 'requires_capture', 'transfer_data': None, 'transfer_group': None}}, 'livemode': False, 'pending_webhooks': 1, 'request': {'id': 'req_JI0oXn4OjEEMlX', 'idempotency_key': '42c3e796-e992-48c1-9c6c-cca778eac935'}, 'type': 'payment_intent.amount_capturable_updated'}
That is looking more like it. Is that working in your construct event function?
not yet. i've always the .SignatureVerificationError: No signatures found matching the expected signature for payload
Checking in, have you tried with this body yet?
Yes @worthy belfry, i've tried with this body but i still have the error above
๐ signature verification error typically is caused by
1/ Incorrect webhook secret
2/ Some middleware in your code parsing the payload (to JSON) before it hits the webhook endpoint
3/ Event not originating directly from Stripe
if there is no solution, i have to change provider..
Are you setting the webhook secret dynamically?
Like do you have multiple webhook secrets stored in a file and retrieving it?
i have 3 webhook secrets stored in a file. but i also tried to set the webhook secrets directly in the construct_event function, but it doesn't work
Can you try hard coding the secret one more time and making sure it belongs to the correct account where the event is getting generated?
disable all the other webhook endpoints just to make sure they don't interfere
the event is generated by one of my connected account which are connecte to my "container" account in which i've implemented the webhook. I'll try to hard coding the secret in the construct_event function one more time. Let me disable all the other webhook
i've tried... i continue to have the same error: stripe.error.SignatureVerificationError: No signatures found matching the expected signature for payload
can you share the event ID you tried with and the webhook endpoint it was delivered on?
the event_id is: we_1NlWdTF6BC6KsJ4hgPZXFmbg
and the webhook endpoint is: http://ec2-15-160-140-97.eu-south-1.compute.amazonaws.com/api/v1/stripe/webhooks/payment-requires-capture
the event ID would start with evt_xxx
oh yes, sorry. That's it: evt_3NuWoPF6BC6KsJ4h0f7hZJgY
Looking into the event, in the meantime you mentioned the event is generated on the connected account.
Is following accurate?
1/ Your platform account has a connect type webhook endpoint where you're listening to these event
2/ You're using platform account webhook endpoint secret
yes, it's right
Hmm actually, that's not right.
The event evt_3NuWoPF6BC6KsJ4h0f7hZJgY was generated by this PaymentIntent create request on acct_1NcNL8F6BC6KsJ4h directly.
https://dashboard.stripe.com/test/logs/req_JI0oXn4OjEEMlX
You don't have any connect type webhook endpoints registered to acct_1NcNL8F6BC6KsJ4h, all three webhooks (two are disabled) are account type. So they can only listen to webhook events generated on that account itself
But, there is the possibility to trigger the three webhooks for all of my acct_**** connected?
So, you will only receive events from acct_1NcNL8F6BC6KsJ4h on all of those webhook endpoints at the moment as they're all registered as "Account" type
Are you 100% sure that you don't have any middleware on your EC2 instance that mutates the request before it reaches your endpoint?
yes, i'm sure.
but now, i'm not sure if i can receive event from all of my connected account
You likely want to read this for connected account webhook events.
https://stripe.com/docs/connect/webhooks
For the signature verification issue, it seems like it'll need a deeper investigation. I'd recommend writing in via our support site here
https://support.stripe.com/?contact=true
Please provide as much information as you can to help us dig deeper
sorry, the link didn't paste correctly.
Updated the above message with the right doc link for connect webhooks