pusher / pusher-http-php

PHP library for interacting with the Pusher Channels HTTP API
https://pusher.com/docs/server_api_guide
1.41k stars 309 forks source link

Can't trigger Pusher events from Laravel to React #341

Closed stesvis closed 2 years ago

stesvis commented 2 years ago

I set up Pusher in my frontend (React) app, and I am able to receive all the events I subscribe to, but ONLY when I send them from the Pusher Debug console.

The problem is when I try to trigger the same event from my Laravel 9 backend. In this case I never receive it in React.

Let me paste some code.

LoginNotificationEvent.php:

class LoginNotificationEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    private $user;

    /**
     * Create a new event instance.
     *
     * @param $user The user that logged in
     */
    public function __construct($user)
    {
        $this->user = $user;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('login-notification.'.$this->user->id);
    }

    public function boradcastAs()
    {
        return 'login-event';
    }
}

channels.php:

Broadcast::channel('login-notification.{userId}', function ($user, $userId) {
    return (int)$user->id === (int)$userId;
});

broadcasting.php:

        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'useTLS' => true,
            ],
        ],

Route that fires the event:

Route::get('/test', function (Request $request) {
    \App\Events\LoginNotificationEvent::dispatch(\Illuminate\Support\Facades\Auth::user());
})->middleware('auth:sanctum');

React code:

  useEffect(() => {
    if (!currentUser) return;

    Pusher.logToConsole = true;

    const pusher = new Pusher(process.env.REACT_APP_PUSHER_APP_KEY, {
      cluster: process.env.REACT_APP_PUSHER_APP_CLUSTER,
    });

    const channel = pusher.subscribe(`login-notification.${currentUser?.id}`);
    console.log("subscribed", channel);

    channel.bind("login-event", function (data) {
      // Code that runs when channel listens to a new message
      console.log("login-notification data", data);
    });

    return () => {
      pusher.unsubscribe(`login-notification.${currentUser?.id}`);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

When I execute the /test route from Postman I can see the number of total messages increase every time in the Pusher console, but I do not receive them in React: https://snipboard.io/OzVwU8.jpg

I made sure that all the Pusher variables match between Laravel and React, so I really don't know what I am doing wrong, in either side... Any missing code? Wrong configuration?

Thanks!

stesvis commented 2 years ago

UPDATE It works if I trigger a public Channel but not with a PrivateChannel.

What is the correct way to subscribe to a private channel?

benw-pusher commented 2 years ago

The process for authenticating for a private channel in Laravel is unique and can be found at https://laravel.com/docs/9.x/broadcasting#authorizing-channels. To subscribe to a private channel in the client you need to prefix the channel name private-, for example private- login-notification.${currentUser?.id}. You will also need to provide an auth endpoint. It appears you are using PusherJS, so you can find info on this setting at https://github.com/pusher/pusher-js#channelauthorization-object

benw-pusher commented 2 years ago

I haven't had a response to this one so I will close it out - if you need further assistance it may be best to get in touch with us at https://support.pusher.com/hc/en-us/requests/new