Error: unable to run private channel using Pusher in Laravel 10

40 views Asked by At

I'm creating a chat feature using pusher private channel. When someone from the same thread sends a message, other people in that thread receive the message.

I have created the code as bellow, but I get error messages:

Error: JSON returned from channel-authorization endpoint was invalid, yet status code was 200

Console

Controller

public function store(Request $request)
{
    $thread = Thread::findOrFail($request->thread_id);

    Message::create([
        'thread_id' => $thread->id,
        'user_id' => Auth::id(),
        'body' => $request->body,
    ]);

    event(new NewMessage($thread->id, Auth::user()->id, $request->body));

    event(new MessageCreated());

    return response()->json([
        'status' => 'success',
        'message' => 'Your message has been sent successfully.',
    ]);
}

Event

<?php

namespace App\Events;

use App\Models\User;
use Cmgmyr\Messenger\Models\Thread;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

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

    public $thread_id;
    public $user_id;
    public $message;

    public function __construct($thread_id, $user_id, $message)
    {
        $this->thread_id = $thread_id;
        $this->user_id = $user_id;
        $this->message = $message;
    }

    public function broadcastOn(): array
    {
        return [
            new PrivateChannel('my-thread.' . $this->thread_id)
        ];
    }

    public function broadcastAs(): string
    {
        return 'new-message';
    }
}

BroadcastServiceProvider

public function boot(): void
{
    Broadcast::routes(['middleware' => ['auth:sanctum']]);

    require base_path('routes/channels.php');
}

Channels route

Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
    return (int) $user->id === (int) $id;
});

Broadcast::channel('my-thread.{threadId}', function ($user,$threadId) {
    $thread = Thread::find($threadId);

    $participant = $thread->participants()->where('user_id', $user->id)->first();

    return (int) $participant->user_id === (int) $user->id;
});

pusher.js

import axios from 'axios';
window.axios = axios;

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

import Echo from 'laravel-echo';

import Pusher from 'pusher-js';
window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: '21fa0caff88313',
    cluster: 'mt1',
    forceTLS: true,
    encrypted: true,
    authorizer: (channel) => {
        return {
            authorize: (socketId, callback) => {
                axios.post('/broadcasting/auth', {
                    socket_id: socketId,
                    channel_name: channel.name
                })
                .then(response => {
                    callback(false, response.data);
                })
                .catch(error => {
                    callback(true, 'error');
                });
            }
        };
    },
});

Pusher.logToConsole = false;
window.pusher = new Pusher('21fa0caff88313', {
    cluster: 'mt1',
    authEndpoint: `/broadcasting/auth`,
    auth: {
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Content-Type": "application/json"
        },
    }
});

console.log('pusher.js loaded');

Blade

@vite('resources/js/pusher.js')
<script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
<script type="module">
    Pusher.logToConsole = true;

    var thread_id = new URL(window.location.href).searchParams.get('id');
    var user_id = "{{ auth()->user()->id }}";

    console.log('private-my-thread.' + thread_id);

    var thread = pusher.subscribe('private-my-thread.' + thread_id);

    thread.bind('new-message', function(data) {
        console.log('new message', data);
        // if (data.thread_id == thread_id) {
            getMessages();
        // }
    });

    var message = pusher.subscribe('my-chat');

    message.bind('message-created', function(data) {
        getMessages();
    });
</script>

From these code examples, I tried private channels and public channels. Public channels can work, but private channels cannot work. How to fix this?

And also, in pusher.js, I put the pusher credentials directly in the file. Because if I make it like the below, the pusher can't work, or I get an error message:

  • Uncaught Options object must provide a cluster
  • Uncaught ReferenceError: pusher is not defined

old-pusher.js

import axios from 'axios';
window.axios = axios;

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

import Echo from 'laravel-echo';

import Pusher from 'pusher-js';
window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
    wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
    wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
    forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
    authorizer: (channel) => {
        return {
            authorize: (socketId, callback) => {
                axios.post('/broadcasting/auth', {
                    socket_id: socketId,
                    channel_name: channel.name
                })
                .then(response => {
                    callback(false, response.data);
                })
                .catch(error => {
                    callback(true, error);
                });
            }
        };
    },
});

window.Pusher.logToConsole = false;
window.pusher = new window.Pusher(import.meta.env.VITE_PUSHER_APP_KEY, {
    cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
    authEndpoint: `/broadcasting/auth`,
    auth: {
        headers: {
        "Access-Control-Allow-Origin": "*",
        
        }
    }
});

Note: i also use laravel messenger package: https://github.com/cmgmyr/laravel-messenger

I have tried making the code as above. For public channels, it was successful, but for private channels, it was not successful.

0

There are 0 answers