#l_webhooks
1 messages · Page 1 of 1 (latest)
👋 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/1403053329839558817
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
Hi there
Can you just drop the relevant snippets from your Webhook endpoint
Shouldn't need 100s and 100s of lines
🧑💻 How to format code on Discord
Inline code: wrap in single backticks (`)
This:
The variable `foo` contains the value `bar`.
Will turn into this:
The variable
foocontains the valuebar.
Code blocks: wrap in three backticks (```)
Also, you can specify the language after the first three backticks to get syntax highlighting.
This:
```javascript
function foo() {
return 'bar';
}
```
Will turn into this:
function foo() {
return 'bar';
}```
Notes about **code blocks**:
- Specifying the language is optional (e.g., you can omit `javascript` in the example above)
- If you don't specify the language you won't get syntax highlighting
- When you're inside a code block (after you type \`\`\`) the `Return`/`Enter` key will add a new line instead of sending your message
- Once you end the code block `Return`/`Enter` works normally again
You can [read more about message formatting on Discord's website.](https://support.discord.com/hc/en-us/articles/210298617)
hi
i send it
th
thx
public function handle(ServerRequestInterface $request)
{
global $db;
$signature = $request->getHeaderLine('stripe-signature');
$body = (string)$request->getBody();
$event = \Stripe\Webhook::constructEvent(
$body,
$signature,
$this->webhookSecret
);
file_put_contents('request_log.txt', print_r($request->getHeaders(), true));
file_put_contents('request_body.txt', $body);
// Traitement des événements Stripe
switch ($event->type) {
case 'invoice.payment_succeeded':
$invoice = $event->data->object;
$invoiceId = $invoice->id;
$customerEmail = $invoice->customer_email ?? null;
$amountPaid = $invoice->amount_paid;
try {
$stmt = $db->prepare("INSERT INTO payments (invoice_id, customer_email, amount) VALUES (?, ?, ?)");
$stmt->execute([$invoiceId, $customerEmail, $amountPaid]);
http_response_code(200);
echo json_encode(['status' => 'success', 'message' => 'Payment processed successfully']);
return;
} catch (\Exception $e) {
http_response_code(500);
echo json_encode(['status' => 'error', 'message' => 'Database error: ' . $e->getMessage()]);
return;
}
default:
error_log('⚠️ Webhook non géré: ' . $event->type);
}
http_response_code(200);
echo json_encode(['status' => 'ok']);
}```
Okay and what exact error do you see?
Fatal error: Uncaught Stripe\Exception\SignatureVerificationException: Unable to extract timestamp and signatures from header in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\Exception\SignatureVerificationException.php:28 Stack trace: #0 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\WebhookSignature.php(31): Stripe\Exception\SignatureVerificationException::factory('Unable to extra...', '', '') #1 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\Webhook.php(29): Stripe\WebhookSignature::verifyHeader('', '', 'whsec_5776baa87...', 300) #2 C:\xampp\htdocs\backend\src\manager\stripeaccount.php(80): Stripe\Webhook::constructEvent('', '', 'whsec_5776baa87...') #3 C:\xampp\htdocs\backend\src\webhook.php(21): Liamo\Backend\manager\stripeaccount->handle(Object(Nyholm\Psr7\ServerRequest)) #4 {main} thrown in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\Exception\SignatureVerificationException.php on line 28
or
<br />
<b>Fatal error</b>: Uncaught Error: Call to a member function prepare() on null in C:\xampp\htdocs\backend\src\manager\stripeaccount.php:100
Stack trace:
#0 C:\xampp\htdocs\backend\src\webhook.php(21): Liamo\Backend\manager\stripeaccount->handle(Object(Nyholm\Psr7\ServerRequest))
#1 {main}
thrown in <b>C:\xampp\htdocs\backend\src\manager\stripeaccount.php</b> on line <b>100</b><br />
but I don't care about that db
That's what i think the more important
file_put_contents('signature_log.txt', $signature);
?
if you talk about this, i didnt dit it
t=1754585711,v1=91fdbd61da5a7964ed482c066cc5fd56fda37dfb76b3286f92f811488c36d2eb,v0=645e2a73fc712a759b67c018ec59e2814b02461eebdf3c8f7b26b0f6222e4efd
Ah yeah sorry I missed that
Hmm what version of the PHP library are you using?
The Stripe PHP SDK I mean
np
If you try to just decode the Event without the signature and endpoint does it work?
Like just doing:
$event = \Stripe\Event::constructFrom(
json_decode($payload, true)
);
i am gonna try
thx
atal error: Uncaught TypeError: array_keys(): Argument #1 ($array) must be of type array, null given in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php:305 Stack trace: #0 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(305): array_keys(NULL) #1 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(276): Stripe\StripeObject->refreshFrom(NULL, NULL, false, 'v1') #2 C:\xampp\htdocs\backend\src\manager\stripeaccount.php(80): Stripe\StripeObject::constructFrom(NULL) #3 C:\xampp\htdocs\backend\src\webhook.php(21): Liamo\Backend\manager\stripeaccount->handle(Object(Nyholm\Psr7\ServerRequest)) #4 {main} thrown in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php on line 305
wtf
When you log out $body what do you see?
Hmm okay that looks fine to me....
it's weird..
👋 Taking over this thread, catching up now
thx
Based on the logs you shared, the information all look fine to me.
With reference to "Unable to extract timestamp and signatures from header" in https://github.com/stripe/stripe-php/blob/master/lib/WebhookSignature.php#L32, this error will be thrown when the timestamp and signature can't be extracted, i.e. $signature in \Stripe\Webhook::constructEvent is malformed
so what i need to do ?
for fix
However, the $signature value you shared earlier looks correct to me
I'm trying to spot what could other possibility be
thank you very much
Could you log entire header, so that I can check what are the headers in the event?
Array
(
[Host] => Array
(
[0] => localhost
[1] => localhost
)
[User-Agent] => Array
(
[0] => Stripe/1.0 (+https://stripe.com/docs/webhooks)
)
[Content-Length] => Array
(
[0] => 5490
)
[Accept] => Array
(
[0] => */*; q=0.5, application/xml
)
[Cache-Control] => Array
(
[0] => no-cache
)
[Content-Type] => Array
(
[0] => application/json; charset=utf-8
)
[Stripe-Signature] => Array
(
[0] => t=1754585711,v1=91fdbd61da5a7964ed482c066cc5fd56fda37dfb76b3286f92f811488c36d2eb,v0=645e2a73fc712a759b67c018ec59e2814b02461eebdf3c8f7b26b0f6222e4efd
)
[Accept-Encoding] => Array
(
[0] => gzip
)
)
It looks to me that $signature for some reason isn't passed correctly here. Do you have a simple reproducible code that I spin up to test out?
what do you mean by " simple reproducible code " ?
a php server with only stripe webhook code that mirrors your server setting / config
from the code, it looks fine to me
it might be due to other reason or config
without being able to reproduce the issue, it's hard to troubleshoot what problem is
I see, because I use PHP as a backend and Vite + React as a frontend.
Webhook is backend only. Frontend shouldn't matter
We only need the reproducible code for backend in PHP with the webhook event handling
hi
@median sedge That's all the code I used for the webhooks
plz i need someone who can help me to fix 😔
Hi 👋
I'm taking over as my colleague has to go.
Can you try using our scripts in our Webhook builder and verify whether or not they work for you?
https://docs.stripe.com/webhooks/quickstart
If the PHP version of that script works for you, then I recommend starting to modify it to match the behavior you have in your current file. But do it one step at a time and test to make sure the code still works. That way you can see which change introduces the error.
Fatal error: Uncaught TypeError: array_keys(): Argument #1 ($array) must be of type array, null given in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php:305 Stack trace: #0 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(305): array_keys(NULL) #1 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(276): Stripe\StripeObject->refreshFrom(NULL, NULL, false, 'v1') #2 C:\xampp\htdocs\backend\src\webhook.php(16): Stripe\StripeObject::constructFrom(NULL) #3 {main} thrown in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php on line 305
Sorry that doesn't make sense.
<?php
require_once '../vendor/autoload.php';
require_once '../env.php';
\Stripe\Stripe::setApiKey(STRIPE_SECRET);
// Replace this endpoint secret with your endpoint's unique secret
// If you are testing with the CLI, find the secret by running 'stripe listen'
// If you are using an endpoint defined with the API or dashboard, look in your webhook settings
// at https://dashboard.stripe.com/webhooks
$endpoint_secret = STRIPE_WEBHOOK_SECRET;
$payload = @file_get_contents('php://input');
$event = null;
try {
$event = \Stripe\Event::constructFrom(
json_decode($payload, true)
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
echo '⚠️ Webhook error while parsing basic request.';
http_response_code(400);
exit();
}
if ($endpoint_secret) {
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
echo '⚠️ Webhook error while validating signature.';
http_response_code(400);
exit();
}
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded($paymentIntent);
break;
case 'payment_method.attached':
$paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached($paymentMethod);
break;
default:
// Unexpected event type
error_log('Received unknown event type');
}
http_response_code(200);```
What line of code is throwing that?
Did you add you API keys?
Yes
And you are running the code you just shared?
Yes
And what line in that code raises this exception?
This error is displayed to me when I open the file "http://localhost/backend/src/webhook.php" (i.e. the one containing the webhook) in the browser
Why are you opening it in the browser?
for watch the error
Webhook handling is purely back-end
Can you please try just running this script as a server and sending a webhook event to it?
what i currently have is the stripe code you told me to put
Right and I'm saying please run it in the terminal
$ php webhook.php
okay
PHP Fatal error: Uncaught TypeError: array_keys(): Argument #1 ($array) must be of type array, null given in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php:305
Stack trace:
#0 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(305): array_keys(NULL)
#1 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(276): Stripe\StripeObject->refreshFrom(NULL, NULL, false, 'v1')
#2 C:\xampp\htdocs\backend\src\webhook.php(16): Stripe\StripeObject::constructFrom(NULL)
#3 {main}
thrown in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php on line 305
Fatal error: Uncaught TypeError: array_keys(): Argument #1 ($array) must be of type array, null given in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php:305
Stack trace:
#0 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(305): array_keys(NULL)
#1 C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php(276): Stripe\StripeObject->refreshFrom(NULL, NULL, false, 'v1')
#2 C:\xampp\htdocs\backend\src\webhook.php(16): Stripe\StripeObject::constructFrom(NULL)
#3 {main}
this is exactly what i have when i am on the browser
Okay I have reproduced that on my end too. This rules out it being something weird with PHP on windows (That has been a problem in the past).
Good, one less variable
hey
Did you follow all the steps we outline in the doc? https://docs.stripe.com/webhooks/quickstart?lang=php
You need to run this like a server. Our doc shows the command php -S 127.0.0.1:4242
I then set up a local listener using our CLI stripe listen --forward-to localhost:4242/webhook.php
In a third terminal window, I triggered a webhook event.
stripe trigger invoice.paid (it generates a lot of webhook events)
I can see the script handling this correctly
Yes
Yes i have it bro
Okay cool!
So start tweaking that code to match what you want to do and see if/when it stops working
Test using the CLI after every change
Okay
So, the error Fatal error: Uncaught TypeError: array_keys(): Argument #1 ($array) must be of type array, null given in C:\xampp\htdocs\backend\vendor\stripe\stripe-php\lib\StripeObject.php:305
Stack trace:
is normal ?
Because you are trying to run this script by itself. It doesn't work like that. It's supposed to receive a webhook request and that is what triggers it.