Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Remote Event Laravel Package

symfony/remote-event

Symfony RemoteEvent component helps you receive and handle remote events from third-party services. It provides a structured way to parse payloads, validate signatures, and dispatch events within your application for consistent, secure integrations.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require symfony/remote-event
    

    For Laravel, also install Symfony’s HTTP components for request handling:

    composer require symfony/http-foundation symfony/http-client
    
  2. Define a Remote Event Class: Create a DTO class annotated with #[RemoteEvent] to represent your webhook payload. Example for Stripe:

    use Symfony\Component\RemoteEvent\Attribute\RemoteEvent;
    
    #[RemoteEvent]
    class StripePaymentSucceededEvent
    {
        public function __construct(
            public string $id,
            public string $amount,
            public string $currency,
        ) {}
    }
    
  3. Create a Consumer: Implement Symfony\Component\RemoteEvent\Consumer\ConsumerInterface to handle the event:

    use Symfony\Component\RemoteEvent\Consumer\ConsumerInterface;
    
    class StripePaymentConsumer implements ConsumerInterface
    {
        public function __invoke(StripePaymentSucceededEvent $event): void
        {
            // Handle payment logic (e.g., update database, send notification)
        }
    }
    
  4. Set Up a Dispatcher: Configure the RemoteEventDispatcher with a consumer resolver (e.g., Symfony\Component\RemoteEvent\Consumer\ConsumerResolver):

    use Symfony\Component\RemoteEvent\RemoteEventDispatcher;
    use Symfony\Component\RemoteEvent\Consumer\ConsumerResolver;
    
    $dispatcher = new RemoteEventDispatcher(
        new ConsumerResolver([StripePaymentSucceededEvent::class => StripePaymentConsumer::class])
    );
    
  5. Handle Incoming Requests: Parse the incoming request and dispatch the event:

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\RemoteEvent\RemoteEventParser;
    
    $request = Request::createFromGlobals();
    $parser = new RemoteEventParser();
    $event = $parser->parse($request, StripePaymentSucceededEvent::class);
    
    $dispatcher->dispatch($event);
    
  6. Add Laravel Integration (Optional): Create a middleware to handle remote events in Laravel’s request pipeline:

    namespace App\Http\Middleware;
    
    use Closure;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\RemoteEvent\RemoteEventParser;
    use Symfony\Component\RemoteEvent\RemoteEventDispatcher;
    
    class RemoteEventMiddleware
    {
        public function __construct(
            private RemoteEventParser $parser,
            private RemoteEventDispatcher $dispatcher
        ) {}
    
        public function handle(Request $request, Closure $next)
        {
            if ($request->isMethod('post') && $request->headers->has('X-Signature')) {
                $event = $parser->parse($request, StripePaymentSucceededEvent::class);
                $this->dispatcher->dispatch($event);
            }
            return $next($request);
        }
    }
    

First Use Case

Stripe Webhook Handling:

  • Replace a custom Stripe webhook controller with a StripePaymentSucceededEvent DTO and consumer.
  • Validate signatures and payloads automatically.
  • Dispatch events to Laravel’s queue for async processing.

Implementation Patterns

Usage Patterns

  1. Event-Driven Workflows:

    • Use Symfony’s Messenger (if integrated) or Laravel’s Bus/Queue to process remote events asynchronously.
    • Example: Dispatch a StripePaymentSucceededEvent to a queue for delayed processing.
  2. Provider-Specific Consumers:

    • Group consumers by provider (e.g., StripeConsumer, GitHubConsumer) and register them in a ConsumerResolver.
    • Example:
      $resolver = new ConsumerResolver([
          StripePaymentSucceededEvent::class => StripePaymentConsumer::class,
          GitHubPushEvent::class => GitHubPushConsumer::class,
      ]);
      
  3. Validation and Security:

    • Leverage Symfony’s built-in signature validation (e.g., HMAC) via RemoteEventParser.
    • Example:
      $parser = new RemoteEventParser(
          new Symfony\Component\RemoteEvent\Validator\SignatureValidator(
              'your-secret-key',
              'sha256'
          )
      );
      
  4. Middleware Pipeline:

    • Chain middleware (e.g., logging, rate limiting) around event dispatching.
    • Example:
      $dispatcher = new RemoteEventDispatcher($resolver, [
          new LogMiddleware(),
          new RateLimitMiddleware(),
      ]);
      
  5. Laravel Integration:

    • Wrap Symfony’s RemoteEventDispatcher in a Laravel service provider:
      namespace App\Providers;
      
      use Illuminate\Support\ServiceProvider;
      use Symfony\Component\RemoteEvent\RemoteEventDispatcher;
      use Symfony\Component\RemoteEvent\Consumer\ConsumerResolver;
      
      class RemoteEventServiceProvider extends ServiceProvider
      {
          public function register()
          {
              $this->app->singleton(RemoteEventDispatcher::class, function ($app) {
                  return new RemoteEventDispatcher(
                      new ConsumerResolver([
                          StripePaymentSucceededEvent::class => $app->make(StripePaymentConsumer::class),
                      ])
                  );
              });
          }
      }
      

Workflows

  1. Webhook Endpoint:

    • Route incoming webhook requests to a Laravel controller or middleware.
    • Parse and dispatch events using RemoteEventParser and RemoteEventDispatcher.
  2. Async Processing:

    • Dispatch events to Laravel’s queue for background processing:
      $dispatcher->dispatch($event); // Uses Symfony Messenger under the hood
      // OR for Laravel:
      dispatch(new HandleRemoteEvent($event));
      
  3. Testing:

    • Mock RemoteEventParser and RemoteEventDispatcher in unit tests.
    • Example:
      $parser = $this->createMock(RemoteEventParser::class);
      $parser->method('parse')->willReturn(new StripePaymentSucceededEvent(...));
      $dispatcher->dispatch($event); // Test consumer logic
      

Integration Tips

  1. Symfony-Laravel Bridge:

    • Use Laravel’s Illuminate\Contracts\Http\Kernel to integrate Symfony’s HttpFoundation request handling.
    • Example:
      use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
      use Illuminate\Http\Request as LaravelRequest;
      
      $symfonyRequest = SymfonyRequest::createFromGlobals();
      $laravelRequest = new LaravelRequest($symfonyRequest->query->all(), $symfonyRequest->request->all(), [], [], [], $symfonyRequest->server->all());
      
  2. Queue Adapters:

    • For async processing, create a Laravel job that wraps Symfony’s RemoteEvent:
      namespace App\Jobs;
      
      use Symfony\Component\RemoteEvent\RemoteEventInterface;
      
      class HandleRemoteEvent implements ShouldQueue
      {
          public function __construct(public RemoteEventInterface $event) {}
      
          public function handle()
          {
              // Process event (e.g., update database, send email)
          }
      }
      
  3. Event Schema Validation:

    • Use Symfony’s Validator component to validate event payloads against JSON Schema:
      use Symfony\Component\Validator\Validation;
      use Symfony\Component\Validator\Constraints\Json;
      
      $validator = Validation::createValidator();
      $constraints = new Json(['schema' => file_get_contents('stripe-schema.json')]);
      $errors = $validator->validate($event, $constraints);
      
  4. Observability:

    • Log event processing with structured data (e.g., event type, timestamp, provider):
      use Psr\Log\LoggerInterface;
      
      class StripePaymentConsumer implements ConsumerInterface
      {
          public function __construct(private LoggerInterface $logger) {}
      
          public function __invoke(StripePaymentSucceededEvent $event): void
          {
              $this->logger->info('Stripe payment succeeded', [
                  'event_id' => $event->id,
                  'amount' => $event->amount,
                  'currency' => $event->currency,
              ]);
          }
      }
      

Gotchas and Tips

Pitfalls

  1. Symfony Dependency Overhead:

    • The package pulls in Symfony components (e.g., HttpFoundation, Messenger), which may conflict with Laravel’s ecosystem.
    • Mitigation: Use symfony/http-foundation and symfony/messenger explicitly to avoid version conflicts.
  2. Request Parsing Differences:

    • Symfony’s HttpFoundation\Request and Laravel’s Illuminate\Http\Request have different APIs.
    • Mitigation: Create a wrapper to convert between the two:
      use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
      use Illuminate\Http\Request as LaravelRequest;
      
      class RequestConverter
      {
          public static function toSymfony(LaravelRequest $laravelRequest): SymfonyRequest
          {
              return SymfonyRequest::create(
                  $laravelRequest->getUri(),
                  $laravelRequest->getMethod(),
                  $laravelRequest->query->all(),
                  $laravelRequest->request->all(),
                  [],
                  ['HTTP_' => array_map('strtoupper', $laravelRequest->header->all())]
              );
          }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport