php 45 lines · 7 steps

Handling Stripe webhooks in Laravel

A controller verifies Stripe's signature, then routes each event type to the right subscription action.

Explained by highlit
1<?php
2 
3namespace App\Http\Controllers;
4 
5use App\Services\SubscriptionService;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Log;
8use Stripe\Exception\SignatureVerificationException;
9use Stripe\Webhook;
10use Symfony\Component\HttpFoundation\Response;
11 
12class StripeWebhookController extends Controller
13{
14 public function __construct(private readonly SubscriptionService $subscriptions)
15 {
16 }
17 
18 public function handle(Request $request): Response
19 {
20 try {
21 $event = Webhook::constructEvent(
22 $request->getContent(),
23 $request->header('Stripe-Signature', ''),
24 config('services.stripe.webhook_secret'),
25 );
26 } catch (SignatureVerificationException $e) {
27 Log::warning('Rejected Stripe webhook with invalid signature', ['error' => $e->getMessage()]);
28 
29 return response()->json(['error' => 'invalid signature'], 400);
30 }
31 
32 $object = $event->data->object;
33 
34 match ($event->type) {
35 'customer.subscription.created',
36 'customer.subscription.updated' => $this->subscriptions->syncFromStripe($object),
37 'customer.subscription.deleted' => $this->subscriptions->markCanceled($object->id),
38 'invoice.payment_succeeded' => $this->subscriptions->recordPayment($object),
39 'invoice.payment_failed' => $this->subscriptions->flagPastDue($object),
40 default => Log::info('Unhandled Stripe event', ['type' => $event->type]),
41 };
42 
43 return response()->json(['received' => true]);
44 }
45}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Always verify a webhook's cryptographic signature before trusting its payload.
  2. 2A match expression cleanly dispatches each event type to a dedicated handler.
  3. 3Return 400 on bad signatures but 200 once accepted, so the sender stops retrying.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Handling Stripe webhooks in Laravel — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code