Im trying to send some text-messages using Nexmo with Laravel.
When I send the message directly in the route it works fine:
Route::get('/sms/send/{to}', function(\Nexmo\Client $nexmo, $to){
$message = $nexmo->message()->send([
'to' => $to,
'from' => '#me',
'text' => 'Sending SMS from Laravel. yay!!!'
]);
Log::info('sent message: ' . $message['message-id']);
});
But when I try to sen an sms using a Notification-class I get the error "Bad credentials". I've been following the official documentation from:
https://laravel.com/docs/5.5/notifications#sms-notifications
Here is the class that extends Notification:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\NexmoMessage;
class KeepGoing extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['nexmo'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your SMS message content');
}
I cant figure out why I get a "Bad credentials"-error when trying to use the Notification-class while its working when done in the route-file?
Thank you!
EDIT:
The controller that calls notify():
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Notifications\KeepGoing;
class NotificationController extends Controller
{
public function index()
{
$user = User::first();
$user->notify(new KeepGoing());
}
}
I should also add that toNexmo() gets called:
public function toNexmo($notifiable)
{
// If i dump($notifiable) I can see the user.
// The $notifiable has the attribute phone_number which is
// what the notificationsystem looks for...
return (new NexmoMessage)
->content('Your SMS message content');
}
Turns out the error was caused by a silly mistake, I messed up the nexmo-config in config/services.php:
'nexmo' => [
'key' => env('NEXMO_KEY'),
'secret' => env('NEXMO_SECRET'),
'sms_from' => '15556666666',
],
I put in the actual key and secret in the above...
You haven't mentioned how you send notifications when you are getting the error but if you use queues, you should make sure you run
php artisan queue:restart
to make process run in queue see your changes (for example modified .env or config)
Related
I'm trying to build a task scheduler for sending email routine and i got this error when i try to get approval_code from auth.
Here are my code in mail:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use App\Services\GetApprovalPersonByRouteCode;
use App\HabisKontrak;
class HabisKontrakMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
* #param HabisKontrak $habisKontrak
* #param [type] $person
* #param [type] $justInfo
*
*/
public function __construct()
{
//
// $this->link = $link;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$reminder_kontrak=HabisKontrak::all();
$person = GetApprovalPersonByRouteCode::getPerson(auth()->user()->approval_code,HabisKontrak::KODE_MODUL);
return $this->subject('Pemberitahuan Karyawan Habis Kontrak')
->view('mail.reminder.habisKontrak')
->with([
'reminder_kontrak' => $reminder_kontrak,
'person' => $person
]);
// }
}
}
and here are code for the GetApprovalPersonByRouteCode
<?php
namespace App\Services;
use DB;
use App\PermintaanKendaraan;
class GetApprovalPersonByRouteCode{
/**
* Get person approval / just info
*
* #param string $approvalCode
* #param string $kode_modul
* #return void
*/
public static function getPerson($approvalCode, $kode_modul){
return DB::table('approvalroutedetail')
->select([
'approvalroutedetail.nik',
'approvalroutedetail.sequence',
'approvalroutedetail.just_info',
'approvalroutedetail.modul',
'approvalroutedetail.approvalroute_id',
'karyawan.nama',
'karyawan.departemensubsub',
'karyawan.email',
'karyawan.jabatan'
])->join('karyawan','approvalroutedetail.nik','karyawan.nik')
->where('approvalroutedetail.modul', $kode_modul)
->where('approvalroutedetail.approvalroute_id', $approvalCode)
->orderBy('approvalroutedetail.sequence','asc')
->orderBy('approvalroutedetail.just_info','asc')
->get();
}
}
I tried to pass the data via constructor like this
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use App\Services\GetApprovalPersonByRouteCode;
use App\HabisKontrak;
use App\Reminder;
use DateTime;
class HabisKontrakMail extends Mailable
{
use Queueable, SerializesModels;
protected $person; //approver (collection: GetApprovalPersonByRouteCode::getPerson)
/**
* Create a new message instance.
* #param HabisKontrak $habisKontrak
* #param [type] $person
* #param [type] $justInfo
*
*/
public function __construct($person)
{
//
$this->person = $person;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$reminder_kontrak=HabisKontrak::all();
return $this->subject('Pemberitahuan Karyawan Habis Kontrak')
->view('mail.reminder.habisKontrak')
->with([
'reminder_kontrak' => $reminder_kontrak,
'person' => $this->person
]);
// }
}
}
And then i got the error massage
Too few arguments to function
App\Mail\HabisKontrakMail::__construct(), 0 passed
I try to get this value getPerson(auth()->user()->approval_code,HabisKontrak::KODE_MODUL), Thankyou.
Task scheduler does not have a user session, thus auth()->user() can only return null (non-object).
To fix this, your crontab command can provide the user argument along. And your command can get a user with arguments:
Arguments
All user supplied arguments and options are wrapped in curly braces. In the following example, the command defines one required argument: user:
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'mail:send {user}';
You may also make arguments optional or define default values for arguments:
// Optional argument...
mail:send {user?}
// Optional argument with default value...
mail:send {user=foo}
Simply pass the load a User object with the user argument (probably the user id or the user name). Pass this User on to HabisKontrakMail object, then you're good to go.
Wait. Doesn't that mean the same user is sending every time?
One catch is you can only have 1 user sending all the notification email. But according to the code you showed, the database don't seem to contain which user actually initiated the notification.
If you need to actually check it, you'll have to store the user id / username for the notification before it is scheduled. And I don't have enough information to suggest anything.
Someone knows how to add headers to emails sent through Laravel Notification System?
I am not talking about Mailable classes where I can set header through the withSwiftMessage() method!
I also would like to keep using the MailMessage once I have a lot of emails built using the line, greetings methods!
Any one has any clue?
There is my code in case somebody needs to see anything!
<?php
namespace PumpMyLead\Notifications\Tenants\Auth;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class AccountActivation extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('My email subject')
->greeting('Just a greeting')
->line('Line 1')
->line('Line 2')
->action('CTA wanted', 'http://www.pumpmylead.com')
->line('Byebye');
}
}
Thanks in advance!
Actually I've found 2 ways to append headers.
When the notification is sent via mail channel an Illuminate\Mail\Events\MessageSending event is fired.
Append a listener to it. In handle() you will get the Swift_Message object.
Or in the AppServiceProvider's register() method override the MailChannel with your own and append the header in the send() method.
$this->app->bind(
\Illuminate\Notifications\Channels\MailChannel::class,
MyMailChannel::class
);
In ./app/Notifications/myNotification.php, add this code in your __construct() function:
$this->callbacks[]=( function($message){
$message->getHeaders()->addTextHeader('x-mailgun-native-send', 'true');
});
Replace the "x-mailgun-native-send" with any header you wish to add,
and 'true' with the desired value.
See https://github.com/laravel/ideas/issues/475
Here's a modern 2022 alternative if the above doesn't work, tested in Laravel 8.
using withSwiftMessage()
public function toMail($notifiable)
{
return (new MailMessage)
->subject($subject)
->greeting($greeting)
->line($line1)
->line($line2)
->withSwiftMessage(function($message) use ($value1, $value2) {
$message->getHeaders()->addTextHeader('X-MJ-CustomID', json_encode([
'key1' => $value1,
'key2' => $value2,
]));
})
}
Debbie V has a pretty close answer but not quite right. The issue she is referencing makes it clear, but she missed the necessary context that solution provided.
By default a Notification in Laravel uses MailMessage, however you can also have it return a Mailable instead. Only if you: a) create a custom mailable, and b) use that instead of MailMessage will the callbacks be applied.
A more complete solution would be:
Create a custom mailable class php artisan make:mail MyMailable
Update your public function toMail($notifiable) method to utilize a the new Mailable.
Add the callbacks to the constructor of your MyMailable class.
And after that you should be all good. The hardest part of this is just adapting the current MailMessage you use to fit the API of a Mailable.
I have a weird issue in my website. I have several Notifications such as Email Verification and Password Reset that are sending properly. However, I made my own notification that sends an url with a UUID to the user and unfortunately, it doesn't send.
I tried every way: 'Notification::route', notify the user directly, nothing works. Actually, notifying the user directly would be bad since I need to send it to an email address not attached to any model.
Anyway, here's the code for the notification. Keep in mind the other notifications work, so I doubt it is the issue.
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class NewEmail extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($uuid)
{
$this->uuid = $uuid;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line(__('messages.newEmailAsked'))
->action(__('messages.newEmailConfirm'), config('app.frontend_url') . '/verify-new-email?code=' . $this->uuid)
->line(__('messages.newEmailIgnore'));
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
public function addNewEmail($email) {
if(User::where('email', $email)->count() === 0) {
$uuid = Str::uuid();
NewEmail::create(['email' => $email, 'unique_code' => $uuid, 'user_id' => $this->id]);
Notification::route('mail', $email)->notify(new \App\Notifications\NewEmail($uuid));
} else {
return 'Email already exists.';
}
}
I really don't get why this notification isn't sent while the other are...
Weirdly enough, the problem fixed itself when I did the actual path the user would take instead of using Tinker.
Just had to $user->addNewEmail($newEmailHere) and it worked properly...
You have not defined the $uuid variable in your Queueable class
I'm new to Laravel. I just created a custom login with laravel 5.7. When I tried to reset password I'm getting this error:
"Declaration of
App\Employee::sendEmailVerificationNotification($token) should be
compatible with
Illuminate\Foundation\Auth\User::sendEmailVerificationNotification()"
Does anyone know how to resolve this error?
You may do something like this
class Employee extends Model implements MustVerifyEmail {
public function sendEmailVerificationNotification()
{
$this->notify(new VerifyEmail);
}
}
if you want to call it like Employee::sendEmailVerificationNotification() and if you want to verify the token you should extend the VerifyEmail notification something like
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Lang;
use Illuminate\Auth\Notifications\VerifyEmail;
class VerifyEmailNotification extends VerifyEmail
{
use Queueable;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($token)
{
//verify token
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
if (static::$toMailCallback) {
return call_user_func(static::$toMailCallback, $notifiable);
}
return (new MailMessage)
->subject(Lang::getFromJson('Verify Email Address'))
->line(Lang::getFromJson('Please click the button below to verify your email address'))
->action(
Lang::getFromJson('Verify Email Address'),
$this->verificationUrl($notifiable)
)
->line(Lang::getFromJson('If you did not create an account, no further action is required.'));
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
Then in Employee model
public function sendEmailVerificationNotification($token)
{
$this->notify(new VerifyEmailNotification($token)); // your custom notification
}
You have to follow the same method signature if you want to override it-
You are overriding this method-
Illuminate\Foundation\Auth\User::sendEmailVerificationNotification()
to this-
App\Employee::sendEmailVerificationNotification($token)
If you notice the difference, you have passed $token in the method while the original method definition does not support that.
Create a different method if you need a different signature from the original method.
I am trying to use the laravel-notifications-channel/onesignal and I am having some problems with users in my laravel app set up to receive notifications. The documentation on the github page does not really cover how a user authenticates them self to receive a notification.
Even reading over the OneSignal docs for sending users to OneSignal is not working for me.
How do I set it up where when a user is using our web app they are notified to receive notifications and then I can send notifications to them using laravel notifications?
Here is my AssignedToTask Notification file:
<?php
namespace App\Notifications;
use App\Task;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use NotificationChannels\OneSignal\OneSignalChannel;
use NotificationChannels\OneSignal\OneSignalMessage;
use NotificationChannels\OneSignal\OneSignalWebButton;
class AssignedToTask extends Notification
{
use Queueable;
protected $task;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(Task $task)
{
//
$this->task = $task;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail', OneSignalChannel::class];
}
public function toOneSignal($notifiable)
{
return OneSignalMessage::create()
->subject("Your {$notifiable->service} account was approved!")
->body("Click here to see details.")
->url('http://onesignal.com')
->webButton(
OneSignalWebButton::create('link-1')
->text('Click here')
->icon('https://upload.wikimedia.org/wikipedia/commons/4/4f/Laravel_logo.png')
->url('http://laravel.com')
);
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('You have been assigned a new task')
->line('You have a new task: ' . $this->task->title)
->action('View Task', url('tasks/' . $this->task->id));
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
In my user model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Zizaco\Entrust\Traits\EntrustUserTrait;
use HipsterJazzbo\Landlord\BelongsToTenants;
use Cmgmyr\Messenger\Traits\Messagable;
class User extends Authenticatable
{
use Notifiable;
use EntrustUserTrait;
use BelongsToTenants;
use Messagable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'company_id'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token', 'company_id'
];
....
public function routeNotificationForOneSignal()
{
return 'ONE_SIGNAL_PLAYER_ID';
}
public function routeNotificationForMail()
{
return $this->email_address;
}
}
How do I set and get the ONE_SIGNAL_PLAYER_ID in user model so a user accepts notifications and I can send them notifications?
EDIT - 2
Since you don't know what's happening is, Let me try to explain how you can work with OneSignal.
This is a push messaging system just like any other push notification system. (FCM (google), PubNub).
How it Works
First goto OneSignal.Com Create your account, and then create an app for you. Once you create an app it will give you SDK for Mobile, where your consumers are.
Now whenever your consumers install and start your app, they will notify your web server with their own unique id and user information.
The information you received about the user is unique player_id which you will store in your database against that user.
Now when you want to send a notification to any mobile app just call the API Post Notification method with player_id and OneSignal will send a push notification to that mobile app.
EDIT - 1
I think now i understand your confusion about Notifications with OneSignalChannel
Flow
You already have the players_ids stored in your app database against every user.
Now when you want to push a notification to a player, you just take that users player_id from db and push a notification to OneSignal.
Well you took this meaning literally. Which was causing issue
public function routeNotificationForOneSignal()
{
return 'ONE_SIGNAL_PLAYER_ID';
}
From the error message this function should have return a unique id (UUID).
Change the return value to actual player id at OneSignalChannel
That's all my friend.