Pusher subscription error. Laravel - laravel

I'm trying to make a chat between two persons in Laravel 5.4 with Pusher.
First, I send an Ajax post request:
$('#btn-chat').click(function (){
$.post('sendMessage',{
_token: $("[name='csrf-token']").attr('content'),
user_id: userId,
chat_id: 1,
message: $('#btn-input').val()
},
function(data) {
console.log(data);
});
});
Then, a controller takes the request:
public function sendMessage(Request $request){
$user = Auth::user();
$message = new Message;
$message->fill($request->all());
$message->message = $request->message;
$message->save();
broadcast(new MessageSent($message))->toOthers();
return 'Return MessageController';
}
Also, here is my MessageSent event:
class MessageSent implements ShouldBroadcast {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public function __construct($message) {
$this->message = $message;
}
public function broadcastOn() {
return new PrivateChannel('chat.'.$this->message->chat_id);
}
}
And my channels.php document:
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('chat.*', function ($user, $chat_id) {
return (int) $user->id === (int) $chat_id;
});
And finally, the JavaScript listens to events:
var pusher = new Pusher('pusher_key', {
cluster: 'us2',
encrypted: true,
authEndpoint: 'broadcasting/auth',
auth: {
headers: {
'X-CSRF-Token': $("[name='csrf-token']").attr('content')
}
}
});
Pusher.logToConsole = true;
var channel = pusher.subscribe('private-chat.1');
channel.bind('MessageSent', (data) => {
alert(data.message);
});
All that should to the work, but when I load the chat page, it throws an error on JavaScript console:
Pusher : No callbacks on private-chat.1 for pusher:subscription_error

Pusher emits events automatically in certain circumstances.
Pusher : No callbacks on private-chat.1 for pusher:subscription_error
Is telling you that there was an error subscribing to the channel, but you haven't bound a callback to that event. You should be able to get more information about the error you experienced during subscription by binding to the subscription:error event. You can find more info here.

As leesio anwsered, Pusher emits events if an error ocurrs.
Afther I added:
channel.bind('pusher:subscription_error', function(data) {
console.log(data);
});
It displayed in console:
JSON returned from webapp was invalid, yet status code was 200.
Because the Laravel broadcasting routes (broadcasting/auth) returned an HTTP response, not the JSON that Pusher needs.
So my solution was create a new route (pusherAuth), and then returning to Pusher the following JSON:
public function pusherAuth(Request $request){
$key = 'xxxxxxxxxxxxx';
$secret = 'xxxxxxxxxxxxxx';
$channel_name = $request->channel_name;
$socket_id = $request->socket_id;
$string_to_sign = $socket_id.':'.$channel_name;
$signature = hash_hmac('sha256', $string_to_sign, $secret);
return response()->json(['auth' => $key.':'.$signature]);
}
Client-side JavaScript:
var pusher = new Pusher('xxxxxxxxxxxxx', {
cluster: 'us2',
encrypted: true,
authEndpoint: 'pusherAuth', //Before 'broadcasting/auth'
auth: {
headers: {
'X-CSRF-Token': $("[name='csrf-token']").attr('content')
}
}
});
And that should do the work. I don't know why I couldn't do it with Laravel broadcasting routes, but I post this answer if anyone has the same problem.
More info:
Pusher auth signatures
PHP HMAC SHA56

Related

Why I can not get message pusher in Laravel?

Here is a private channel:
public function broadcastOn()
{
// Here I get $user object successfully
return new PrivateChannel('user-'.$this->user->id); // it is 1
}
The permissions are:
Broadcast::channel('user-{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
The sender is:
Route::post('sender', function () {
PrivateEvent::dispatch(Auth::user());
})->middleware('auth:sanctum');
The client was tested in pusher debug console, it works:
var channel = pusher.subscribe('user-1');
channel.bind('PrivateEvent', function(data) {
alert(JSON.stringify(data));
});
Why when I send message using routing I dont get the message in JS? JS has not errors too.

Laravel livewire not handle listener from broadcast

I tried to listen event emited from broadcast in laravel livewire but nothing happen;
on my bootstrap.js i have:
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'myKey',
wsHost: window.location.hostname,
wsPort: 6001,
disableStat: true,
forceTLS: false,
});
my event laravel
class TaskFinished implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct()
{
//
}
public function broadcastAs(){
return 'task-finish';
}
public function broadcastOn()
{
return new Channel('TaskTricolor');
}
}
my listener
class SendTaskNotif
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param TaskFinished $event
* #return void
*/
public function handle(TaskFinished $event)
{
}
}
and my livewire component
protected $listeners = ['echo:TaskTricolor,TaskFinished' => 'eventlisten'];
// public function getListeners(){
// return [
// 'echo:TaskTricolor,TaskFinished' => 'eventlisten'
// ];
// }
public function start(){
$this->start = true;
$tricolors = new TricolorController();
$this->tricolor = $tricolors->start();
}
public function stop(){
$this->start = false;
$tricolors = new TricolorController();
$this->tricolor = $tricolors->stop();
}
public function emet(){
event(new TaskFinished());
}
public function eventlisten(){
$vars = "test";
dd($vars);
}
on my listener i put dd('test') and when the emet function is called, the dd value is showed;
So when i test with livewire listener handler, nothing happen, my dd not appear, and no error;
I tried to console log Echo from blade to test if i can handle listener, but it show that Echo is not defined, but when i console.log window, i see Echo inside
On my websocket dashboard i have this:
I don't know if it can help to solve, i use beyondcode/laravel-websockets package as driver
When I first started to use Livewire (version 1.0) we listened the messages using vanilla javascript and then called the Livewire.
document.addEventListener("DOMContentLoaded", function () {
window.Echo.private('TaskTricolor')
.listen('.task-finish', (response) => {
window.Livewire.emit('task-finish', response));
}
});
You can try this. It's not a clean solution as your approach, but I think is easier to debug.
I found the issue; on my event class i should use ShouldBroadCastNow instead ShouldBroadCast
class TaskFinished implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct()
{
//
}
public function broadcastAs(){
return 'task-finish';
}
public function broadcastOn()
{
return new Channel('TaskTricolor');
}
}
the ShouldBroadCast put the event in queue, so it's not activated on event called, but ShouldBroadCastNow listen the event immediately, here link i found the explanation
add metadata in your template
<meta name="csrf-token" content="{{ csrf_token() }}">
declare token in your boostrap.js
let token = document.head.querySelector('meta[name="csrf-token"]');
window.Echo = new Echo({
broadcaster: 'push',
.....
...
auth: {
headers: {
Authorization: 'Bearer' + token,
},
},
and call event with
document. addEventListener("DOMContentLoaded", function () {
window.Echo.private('TaskTricolor')
.listen('.task-finish', (response) => {
window.Livewire.emit('task-finish'));
}
});

laravel broadcasting Broadcasting in private chanel not working i use laravel echo

event is:
public $chat ;
public function __construct($chat)
{
$this->chat = $chat;
}
public function broadcastOn()
{
// return new Channel('recieve-chat');
return new PrivateChannel('recieve-chat' );
}
routes/channels.php is:
Broadcast::channel('recieve-chat', function ($user ) {
return true;
// return $user->id === $reciever_id;
});
in blade file:
<script>
window.addEventListener('DOMContentLoaded' , function () {
Echo.private('recieve-chat')
.listen('ChatBroad', (e) => {
window.livewire.emit('recieve:' + e.chat.bid_id , e.chat);
$(chatScrollDown('.chat'+ e.chat.bid_id ));
});
});
</script>
broadcast Channel work properly. but in PrivateChannel is not working. and in console not showing any error
i use laravel echo and pusher
in App\Providers\BroadcastServiceProvider.php
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
}
must like the code. in Broadcast::routes() we dont need any middleware.

Pusher not updating in realtime with laravel echo, laravel and vue js chat application

I've been following this tutorial to learn build real-time chat application with Laravel, Vue js, Laravel Echo and Pusher js.
I've set my BROADCAST_DRIVER=pusher in env and set pusher id, key, secret and cluster correctly.
Pusher config in bootstrap.js:
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
forceTLS: true
});
Snippet from app/Events/NewMessage.php:
use App\Message;
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public function __construct(Message $message)
{
$this->message = $message;
}
public function broadcastOn()
{
return new PrivateChannel('messages.' . $this->message->to);
}
public function broadcastWith()
{
return ['message' => $this->message];
}
}
Code snippet from controller
public function send(Request $request)
{
$message = Message::create([
'from' => auth()->id(),
'to' => $request->contact_id,
'message' => $request->text
]);
broadcast(new NewMessage($message));
return response()->json($message);
}
Code from main vue component that handels the event:
methods: {
saveNewMessage(text) {
this.loadMessages.push(text);
},
handelIncoming(message) {
if (
this.selectedContact &&
message.from == this.selectedContact.id
) {
this.saveNewMessage(message);
return;
}
alert(message.text);
}
},
mounted() {
Echo.private(`messages.${this.user.id}`).listen("NewMessage", e => {
this.hanleIncoming(e.message);
});
axios.get("/contacts").then(response => {
this.contacts = response.data;
});
}
Code from channels.php
Broadcast::channel('messages.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
With the above code I can send and receive the message but not in real-time I have to reload the page or click the component again.
I've also checked the comment section in the video, many people were having same issues. Some of them had suggested to clear cache.
I tried uninstalling and reinstalling the packages, cleared cache, dump-autoload but still the same result.
The tutorial was made 2 years back and I'm doing it now on the latest laravel, pusher, echo versions. Has there been drastic changes in the applications that they don't run on old methods ?
the reason is that this event is fire and add to queue and you must run command
queue:work
to run.
is better to use ShouldBroadcastNow to fire your event immediately.

Why I don't receive broadcast message Laravel Pusher?

My event broadcast looks as:
class OrderStatusUpdate implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $username;
public $message;
public function broadcastAs()
{
return 'my-event';
}
public function __construct($username)
{
$this->username = $username;
$this->message = "Order status by {$username} was changed";
}
public function broadcastOn()
{
return ['my-event'];
}
}
Call event like:
Route::get('/', function () {
OrderStatusUpdate::dispatch('Nick');
return "Event has been sent!";
});
Client side is:
var pusher = new Pusher('018814b79958ee4f2ad1d', {
cluster: 'eu',
forceTLS: true
});
var channel = pusher.subscribe('my-event');
channel.bind('my-event', function(data) {
alert(JSON.stringify(data));
});
All .env settings are correct!
As you can see I use default Laravel settings and channel name. But message comes with error in Pusher server. But I dont get them on HTML page, with code JS showed upper.
Let me explain from client side:
var channel = pusher.subscribe('order');
channel.bind('OrderStatusUpdate', function(data) {
alert(JSON.stringify(data));
});
order id name of channel
OrderStatusUpdate is event name Event
It mean server should be:
public function broadcastAs()
{
return 'OrderStatusUpdate'; // Event name
}
public function broadcastOn()
{
return ['order'];
}
But I am not sure about this array sintax: return ['order'];, try instead this:
public function broadcastOn()
{
return new Channel("order");
}

Resources