Weird Issue with Laravel Slack Notification - laravel

I am new in Laravel and I am trying to send Slack Notification each time an order is placed. For testing, I used my Incoming Webhook. Now when I am changing the webhook to clients slack webhook. Its still sending the notification to old webhook.
Can you help me sort this out?
This is my Listener
public function handle(OrderConfirmed $event)
{
$admin=User::find(73);
$user=User::find($event->order->user_id);
$order=Order::find($event->order->id);
Notification::send(User::find(73),(new \App\Notifications\PaymentProcessedNot($user,$order)));
}
This is my PaymentProcessedNot class
class PaymentProcessedNot extends Notification implements ShouldQueue
{
use Queueable;
public $user;
public $order;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(\App\User $user,\App\Order $order)
{
$this->user=$user;
$this->order=$order;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['slack'];
}
public function toSlack($notifiable){
return (new SlackMessage)
->success()
->content('A new Payment was just processed.')
->attachment(function ($attachment){
$attachment->title('Order : '. $this->order->order_id)
->fields([
'Amount' => ' ₹'. number_format($this->order->amount,2),
'From' => $this->user->name,
'Payment Mode' => strtoupper($this->order->payment_mode)
]);
});
}
}
This is my User.php
public function routeNotificationForSlack()
{
return 'new_slack_incoming_webhook';
}

If your using .env you should clear the cache!
Just checking this is actually the url right?
return 'new_slack_incoming_webhook';

Related

Broadcast event to Pusher when database notification is created

This is related to an earlier question I asked: Am I overcomplicating events/listeners/notifications?.
Based on the feedback received on that question, I modified my approach to attempt to do the following:
Fire a database notification.
Listen for a new database notification to be created
Fire an event and broadcast that to pusher.
So first I send the database notification:
Notification::send($this->requestedBy, new SendMonthlySummaryCreatedNotification($fileDownloadUrl, $fileName));
That notification class looks like this:
class SendMonthlySummaryCreatedNotification extends Notification implements ShouldQueue
{
use Queueable;
public $fileDownloadUrl;
public $fileName;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($fileDownloadUrl, $fileName)
{
$this->fileDownloadUrl = $fileDownloadUrl;
$this->fileName = $fileName;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['database'];
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
'title' => 'Monthly Summary Complete',
'message' => "{$this->fileName} is ready. ",
'link' => $this->fileDownloadUrl,
'link_text' => 'Click here to download',
'show_toast' => true,
'user_id' => $notifiable->id
];
}
}
I found this example of how to add a $dispatchesEvents property to a model in the docs, which I modified to apply it to a new model I created that extends the DatabaseNotification class, which I learned about on this SO question.
class Notification extends DatabaseNotification
{
use HasFactory;
protected $dispatchesEvents = [
'created' => NotificationCreatedEvent::class
];
public function users()
{
return $this->belongsTo(User::class, 'notifiable_id');
}
}
Theoretically the above should dispatch an event when my notification is sent, and then I have the NotificationCreatedEvent that I'd like to use to broadcast to pusher:
class NotificationCreatedEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
protected $notification;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Notification $notification)
{
$this->notification = $notification;
Log::debug($this->notification);
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('users.' . $this->notification->notifiable_id);
}
}
The problem is that everything is working up until the NotificationCreatedEvent It doesn't seem to be getting fired. I don't know if I need to do anything in addition to mapping it in my new Notification model, or if it should just work.
My goal is to add a database notification, and then whenever that happens to send it to pusher so I can notify the user in real-time. This seems like it should work, but I'm not seeing anything coming over in pusher.

how to send notification from admin to user by id with Laravel Pusher

I have successfully implemented pusher on my laravel app but I want to make, when the user succeeds in making an order the default status_message for the order is pending, the case is when the admin changes the status_message to processed, the user who has ordered gets a notification that the order he has made is processed.
this is my code but this code sends notifications to all users.
Controller
if ($data->status_message == 'processed') {
event(new OrderEvent('Hi, Your order is processed!'));
//...
}
My Event OrderEvent.php
public function broadcastOn()
{
return new Channel('notif-channel');
}
/**
* Broadcast order event.
*
* #return void
*/
public function broadcastAs()
{
return 'order-event';
}
in App blade
var channel = pusher.subscribe('notif-channel');
channel.bind('order-event', function(data) {
const obj = JSON.parse(JSON.stringify(data));
const message = obj.message;
blah blah blah
}
Both user and admin should be on the same channel. For example if user is subscribed for channel 'order-channel-SetUserID'.
Admin should send the message to that channel and you should look for it on the front end and make the changes on the DOM.
In your controller when you submit the changes of the status of the order run the event with the channel name
event(new OrderEvent($user_id, 'Hi, Your order is processed!'));
Now your event should look similar to this:
class OrderEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user_id;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($user_id, $message)
{
$this->user_id = $user_id;
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('order-channel.' . $this->user_id);
}
public function broadcastAs()
{
return 'order-event';
}
}
Of course you can change your class Name etc... I'm just giving an idea.
it's important to send the changes on the same channel with this user or else you will make changes to other users that are visiting your website.
EDITED
Here is what else you need to configure.
In app/Providers/EventServiceProvider.php
You need to put the event in protected $listen
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
OrderEvent::class => [
OrderEventListener::class,
],
];
In app/Listeners You should create OrderEventListener.php and set it up as follow:
<?php
namespace App\Listeners;
use App\Events\OrderEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Pusher;
class OrderEventListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param \App\Events\OrderEvent $event
* #return void
*/
public function handle(OrderEvent $event)
{
$pusher = new Pusher(env('PUSHER_APP_KEY'),
env('PUSHER_APP_SECRET'), env('PUSHER_APP_ID'), [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true
]);
$pusher->trigger($event->broadcastOn(),
$event->broadcastAs(), $event->data);
}
}
check your Debug Console in pusher dashboard? If you can see the event firing there all you need to do is show the message with javascript. If no event is running then something in your code is missing.

Laravel Echo with Pusher and Livewire - not receiving notifications client-side

I'm able to broadcast a notification to Pusher, but I'm unable to receive the response back in my livewire component.
Here is my Notification class:
<?php
namespace App\Notifications;
use App\Models\Statement;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class StatementCompletedNotification extends Notification implements ShouldQueue, ShouldBroadcast
{
use Queueable;
public $statement;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(Statement $statement)
{
$this->statement = $statement;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['database', 'broadcast'];
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->statement->uploadedBy->id,
'statement_id' => $this->statement->id,
'file_name' => $this->statement->original_file_name
];
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('users.' . $this->statement->uploadedBy->id);
}
}
And here is the getListeners() method on my Livewire component. I've tried several different things here, first off I tried the way it's shown in the docs, just by referencing my StatementCompletedNotification in the listener, like so:
public function getListeners()
{
return [
"echo-private:users.{$this->user->id},StatementCompletedNotification" => 'refreshNotifications'
];
}
I noticed that in pusher, my event type is listed as Illuminate\Notifications\Events\BroadcastNotificationCreated, and I found this post online, so I tried that method like so:
public function getListeners()
{
return [
"echo-private:users.{$this->user->id},.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated" => 'refreshNotifications'
];
}
Neither way has worked for me.
Here's where I'm attempting to just get something back in my javascript on the client-side:
Echo.private('users.1')
.notification((notification) => {
console.log(notification);
});
I don't get any response and I have no idea what the problem is. I've spent an insane amount of time on this and can't seem to figure it out.
Also, it appears that my notification is being picked up multiple times in the queue:
A little more background, the flow that I have set up right now is basically:
StatementCompleted event gets fired (not queued), there's a listener that handles the StatementCompleted event which is queued, and calls my StatementCompletedNotification class like so:
public function handle($event)
{
$event->statement->uploadedBy->notify(new StatementCompletedNotification($event->statement));
}

Laravel send notification as super-admin from admin controller

I have Super-Admin and Admin roles. In Admin view I've added button to request verification email. The problem I'm having is that when Admin clicks the button to receive verification email, the email is from Admin, not Super-Admin.
How to make this to be sent to Admin from Super-Admin, instead of from Admin?
Route:
Route::post('/dashboard/SendEmailVerification', 'AdminDashboardController#SendEmailVerification')->name('dashboard.SendEmailVerification');
In AdminDashboardController:
use App\Notifications\EmailVerification;
use App\User;
.............
public function SendEmailVerification(Request $request){
$user = User::where('email_verification_code', $request->code)
->withoutGlobalScope('active')
->first();
$user->notify(new EmailVerification($user));
return Reply::success('Email sent!');
}
And the notification email:
namespace App\Notifications;
use App\Traits\SmtpSettings;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use App\User;
class EmailVerification extends Notification implements ShouldQueue
{
use Queueable, SmtpSettings;
protected $user;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
$this->setMailConfigs();
}
/**
* Get the notification's delivery channels.
*t('mail::layout')
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
$via = ['mail'];
return $via;
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Confirm your email')
->greeting(__('Hello!'))
->line(__('email.emailVerify.text'))
->action('Confirm', getDomainSpecificUrl(route('front.get-email-verification', $this->user->email_verification_code), $this->user->company));
#->line(__('email.thankyouNote'));
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return $notifiable->toArray();
}
}
You're getting wrong sender address because you never defined who's the sender in your Notification configuration. There are two ways to do this:
First: The first one is a really simple, but non-dynamic solution. In your .env configuration config, add these lines:
MAIL_FROM_NAME="My Name"
MAIL_FROM_ADDRESS=support#example.com
When you configure this, add this in yout config/mail.php configuration:
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'default value if not found in .env'),
'name' => env('MAIL_FROM_NAME', 'default value if not found in .env'),
],
Note: Don't forget to clear your cache, and restart queue when you do this:
Second: This is a more dynamic solution, since you can load the sender email address from your database. In your SendEmailVerification method, you can query up the super-admin user, and pass to the EmailVerification class:
public function SendEmailVerification(Request $request){
$user = User::where('email_verification_code', $request->code)
->withoutGlobalScope('active')
->first();
$superAdminUser = User::where('role', 'super-admin')->first();
$user->notify(new EmailVerification($user, $superAdminUser));
return Reply::success('Email sent!');
}
Then, change your EmailVerification class:
public $user;
public $superUser;
public function __construct(User $user, User $superUser)
{
$this->user = $user;
$this->superUser = $superUser;
$this->setMailConfigs();
}
And in your toMail() method, add another from() method:
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Confirm your email')
->from($superAdminUser->email, $superAdminUser->first_name)
->greeting(__('Hello!'))
->line(__('email.emailVerify.text'))
->action('Confirm', getDomainSpecificUrl(route('front.get-email-verification', $this->user->email_verification_code), $this->user->company));
#->line(__('email.thankyouNote'));
}
Note: Also clear your cache and restart your queue.
Hope that this can resolve your issue. Let me know if you have any problems with these solutions.
You can read more about notifications on official documentation.

Laravel 5.8 on demand notification error Call to a member function create() on null

When I do this, the user receives email without error:
Notification::send($user, new TicketNotification($details));
But, when I do this, the user also receives an email, but with an error in the screenshot below
Notification::route('mail', 'email_of_non-db_user')->notify(new TicketNotification($details));
Error: Call to a member function create() on null
Do have any idea why? How can I avoid this error?
I have to use On Demand Notification because I need to send a notification to someone who is not stored as a "user".
i think try this one
in TicketNotification update via method with this for only send to mail.
But u r also saved notification into database..
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
Thanks Jignesh, your answer works.
Sorry Thamer, I should have posted the whole code from the beginning.
Before, it was :
return ['mail','database'];
Now only :
return ['mail'];
Then, there is no error anymore.
Here my TicketNotification that made the error:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class TicketNotification extends Notification
{
use Queueable;
private $details;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail','database'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject($this->details['subject'])
->greeting($this->details['title'])
->line($this->details['body'])
->line($this->details['links'])
;
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toDatabase($notifiable)
{
return [
'order_id' => $this->details['order_id']
];
}
}
Add this to your via method to use the same Notification for all your issues:
public function via($notifiable)
{
$availableChannels = [
'mail' => 'mail',
'database' => 'database',
'slack' => 'slack',
'telegram' => TelegramChannel::class
];
$channels = [];
foreach ($availableChannels AS $channel => $driver) {
if ($notifiable->routeNotificationFor($channel)) {
$channels[] = $driver;
}
}
return $channels;
}
You can now use On-Demand Notifications or fire the notificaton on users, without having to make multiple Notifications for each Channel or ON-DEMANDS etc...

Resources