#vincent-goossens_api
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/1265223235256193064
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Hi, let me help you with this.
Could you please share the code of your webhook handler?
Hi, thank you for your response
here some more info:
[2024-07-23 07:54:15] local.DEBUG: sig_header:t=1721721255,v1=85bf1719400a2bfa33f*****************,v0=127d05144acc0e0019e9*****************
[2024-07-23 07:54:15] local.DEBUG: sig_header:t=1721721255,v1=dcff76ef5e080be8f35ad32*****************,v0=b587c49bd446d1d2*****************
[2024-07-23 07:54:15] local.DEBUG: sig_header2:t=1721721255,v1=85bf1719400*****************,v0=127d05144ac*****************
[2024-07-23 07:54:15] local.DEBUG: sig_header2:t=1721721255,v1=dcff76ef5e0*****************,v0=b587c49bd44*****************
[2024-07-23 07:54:15] local.DEBUG: Signature:85bf1719400a2bfa3***************** Expected Signature:1c5f368caac8a45c*****************
[2024-07-23 07:54:15] local.DEBUG: Signature:dcff76ef5e080be8f35*****************, Expected Signature:1c5f368caac8a45*****************
public function handleStripeWebhooks(): JsonResponse
{
Log::debug('here');
// The library needs to be configured with your account's secret key.
// Ensure the key is kept out of any version control system you might be using.
$stripe = new \Stripe\StripeClient(config('stripe.stripe_key'));
// This is your Stripe CLI webhook secret for testing your endpoint locally.
$endpoint_secret = config('stripe.stripe_secret');
Log::debug('secret:'.$endpoint_secret);
Log::debug('stripe:'.config('stripe.stripe_key'));
$payload = $this->request->json();
Log::debug(gettype($payload));
//$payload2 = @file_get_contents('php://input');
$sig_header2 = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$sig_header = $this->request->header('stripe-signature');
Log::debug('sig_header:'.$sig_header);
Log::debug('sig_header2:'.$sig_header2);
//Log::debug('payload:'.$payload);
//Log::debug('payload2:'.$payload2);
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
json_encode($payload), $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
Log::debug('Invalid payload');
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
Log::debug('Invalid signature. message:'.$e->getMessage());
http_response_code(400);
exit();
}
Log::debug($event->type);
Log::debug($event->data->object);
// Handle the event
switch ($event->type) {
case 'customer.created':
$customer = $event->data->object;
case 'customer.deleted':
public static function verifyHeader($payload, $header, $secret, $tolerance = null)
{
// Extract timestamp and signatures from header
$timestamp = self::getTimestamp($header);
$signatures = self::getSignatures($header, self::EXPECTED_SCHEME);
if (-1 === $timestamp) {
throw Exception\SignatureVerificationException::factory(
'Unable to extract timestamp and signatures from header',
$payload,
$header
);
}
if (empty($signatures)) {
throw Exception\SignatureVerificationException::factory(
'No signatures found with expected scheme',
$payload,
$header
);
}
// Check if expected signature is found in list of signatures from
// header
$signedPayload = "{$timestamp}.{$payload}";
$expectedSignature = self::computeSignature($signedPayload, $secret);
$signatureFound = false;
foreach ($signatures as $signature) {
Log::debug('Signature:'.$signature. ', Expected Signature:'.$expectedSignature);
if (Util\Util::secureCompare($expectedSignature, $signature)) {
$signatureFound = true;
break;
}
}
Laravel with the "stripe/stripe-php": "^14.10"
Are you required to verify header manually?
Or is this not your own function?
this is not my code, this is this line of the library "stripe/stripe-php": "^14.10"
https://github.com/stripe/stripe-php/blob/master/lib/WebhookSignature.php#L51
I just added there a log to check what is going wrong over there
Could you try using the latest version?
yes, let me check
๐ taking over for my colleague. Let me know if there's any follow-up Qs I can answer!
would you mind checking this guide https://docs.stripe.com/webhooks/signature first ?
the same on the last version, let me check the Troubleshoot document
I have checked the document and now getting the request more like the Raw data to avoid theat Laravel (framework) changing some
I will share here with you this raw data
HEADERS:
[2024-07-23 09:05:58] local.DEBUG: POST /api/admin-api/v1/payments/webhooks/stripe HTTP/1.1
Accept-Encoding: gzip
X-Forwarded-Proto: https
X-Forwarded-Host: 432d-95-92-71-90.ngrok-free.app
X-Forwarded-For: 54.187.174.169
Stripe-Signature: t=1721725557,v1=8cd5918aeb4f41aa973d9939c8f5ba71eb4ad75ebd0baa738e7793afee9776f4,v0=6960baf04944758214984b6d812e6df59c770db939546bc1728f3172f140634e
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
Accept: /; q=0.5, application/xml
Content-Length: 5667
User-Agent: Stripe/1.0 (+https://stripe.com/docs/webhooks)
Host: 432d-95-92-71-90.ngrok-free.app
body
I'm not sure why do you need to handle the Stripe-Signature manually though
ok
public function handleStripeWebhooks(): JsonResponse
{
Log::debug('here');
// The library needs to be configured with your account's secret key.
// Ensure the key is kept out of any version control system you might be using.
$stripe = new \Stripe\StripeClient(config('stripe.stripe_key'));
// This is your Stripe CLI webhook secret for testing your endpoint locally.
$endpoint_secret = config('stripe.stripe_secret');
Log::debug('secret:'.$endpoint_secret);
Log::debug('stripe:'.config('stripe.stripe_key'));
$payload = $this->request->json();
$payload1Raw = $this->request->getContent();
Log::debug('$payload1Raw:'.$payload1Raw);
Log::debug(gettype($payload));
//$payload2 = @file_get_contents('php://input');
$sig_header2 = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$sig_header = $this->request->header('stripe-signature');
$request = "$_SERVER[REQUEST_METHOD] $_SERVER[REQUEST_URI] $_SERVER[SERVER_PROTOCOL]\r\n";
foreach (getallheaders() as $name => $value) {
$request .= "$name: $value\r\n";
}
$request .= "\r\n" . file_get_contents('php://input');
Log::debug($request);
Log::debug('sig_header:'.$sig_header);
Log::debug('sig_header2:'.$sig_header2);
//Log::debug('payload:'.$payload);
//Log::debug('payload2:'.$payload2);
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload1Raw, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
Log::debug('Invalid payload');
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
Log::debug('Invalid signature. message:'.$e->getMessage());
http_response_code(400);
exit();
}
in that case the problem could just be the webhook endpoint secret
are you using the correct one?
I am using the ones from the test mode in the dashboard
the whsec_xxx ?
but at this point only the secret is used correct ?
STRIPE_KEY=pk_test_51P*********************************************
STRIPE_SECRET=sk_test_51PN************
like this
you need to use the webhook endpoint secret
to verify the signature
not your Stripe API secret
you need to use the webhook endpoint secret
to verify the signature
not your Stripe API secret
yes then I am doing fine:
no these are the API keys
the one you need to use is the one under Webhooks
then you go to your webhook endpoint
and then you click on Reveal Secret
the webhook endpoint secret has a whsec_xxx format
yes
it's explained in the guide I shared with you https://docs.stripe.com/webhooks/signature#check-the-endpoint-secret