#l_webhooks

1 messages · Page 1 of 1 (latest)

pure lotusBOT
#

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

quaint urchin
#

my code is too long

#

how i can send

#

sourcebin?

nova vessel
#

Hi there

#

Can you just drop the relevant snippets from your Webhook endpoint

#

Shouldn't need 100s and 100s of lines

pure lotusBOT
#

🧑‍💻 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 foo contains the value bar.

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)
quaint urchin
#

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']);
    }```
nova vessel
#

Okay and what exact error do you see?

quaint urchin
# nova vessel 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-&gt;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

quaint urchin
nova vessel
#

Hvae you logged out the $signature here?

#

Before actually calling constructEvent()?

quaint urchin
#

?

#

if you talk about this, i didnt dit it

#

t=1754585711,v1=91fdbd61da5a7964ed482c066cc5fd56fda37dfb76b3286f92f811488c36d2eb,v0=645e2a73fc712a759b67c018ec59e2814b02461eebdf3c8f7b26b0f6222e4efd

nova vessel
#

Ah yeah sorry I missed that

#

Hmm what version of the PHP library are you using?

#

The Stripe PHP SDK I mean

quaint urchin
#

2025-06-30.basil

#

this is the version i am using

quaint urchin
nova vessel
#

That's the API version

#

But what version of the PHP SDK?

quaint urchin
#

oh

#

sorry

#

17.4.0

nova vessel
#

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)
  );
quaint urchin
#

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

nova vessel
#

When you log out $body what do you see?

nova vessel
#

Hmm okay that looks fine to me....

quaint urchin
#

it's weird..

pure lotusBOT
median sedge
#

👋 Taking over this thread, catching up now

quaint urchin
#

thx

median sedge
#

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

GitHub

PHP library for the Stripe API. . Contribute to stripe/stripe-php development by creating an account on GitHub.

quaint urchin
#

for fix

median sedge
#

However, the $signature value you shared earlier looks correct to me

#

I'm trying to spot what could other possibility be

quaint urchin
#

thank you very much

median sedge
#

Could you log entire header, so that I can check what are the headers in the event?

quaint urchin
# median sedge Could you log entire header, so that I can check what are the headers in the eve...
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
        )

)
median sedge
#

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?

quaint urchin
median sedge
#

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

quaint urchin
median sedge
#

Webhook is backend only. Frontend shouldn't matter

#

We only need the reproducible code for backend in PHP with the webhook event handling

pure lotusBOT
quaint urchin
#

hi

#

@median sedge That's all the code I used for the webhooks

#

plz i need someone who can help me to fix 😔

keen bay
#

Hi 👋

I'm taking over as my colleague has to go.

quaint urchin
#

oKAY thxx

#

im gonna try

keen bay
#

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.

quaint urchin
# keen bay If the PHP version of that script works for you, then I recommend starting to mo...

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

keen bay
#

Sorry that doesn't make sense.

quaint urchin
#
<?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);```
keen bay
#

What line of code is throwing that?

quaint urchin
#

noneeeeeeeee

#

i just send the code i upload

keen bay
#

Did you add you API keys?

quaint urchin
#

Yes

keen bay
#

And you are running the code you just shared?

quaint urchin
keen bay
#

And what line in that code raises this exception?

quaint urchin
keen bay
#

Why are you opening it in the browser?

quaint urchin
keen bay
#

Webhook handling is purely back-end

quaint urchin
keen bay
#

Can you please try just running this script as a server and sending a webhook event to it?

quaint urchin
#

what i currently have is the stripe code you told me to put

keen bay
#

Right and I'm saying please run it in the terminal

$ php webhook.php
quaint urchin
#

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

keen bay
#

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

quaint urchin
#

Good, one less variable

pure lotusBOT
quaint urchin
#

hey

keen bay
#

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

quaint urchin
#

speaking about this ?

keen bay
#

Yes

quaint urchin
#

Yes i have it bro

keen bay
#

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

quaint urchin
#

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 ?

keen bay
#

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.

quaint urchin
#

in the CLI ?

#

ohhh