enniel / laravel-fcm-notification-channel

MIT License
22 stars 23 forks source link

CouldNotSendNotification thrown even when notification was sent successfully #4

Open tusharvikky opened 7 years ago

tusharvikky commented 7 years ago

Hello,

"Notification was not sent. You should specify device token(s), topic(s) or group(s) for sending notification."

However, laravel-fcm.log logs [2017-05-13 20:37:29] Laravel-FCM.INFO: notification send to 1 devices success: 1 failures: 0 number of modified token : 0 [] [] and the push notification was successfully delivered.

enniel commented 7 years ago

show your code in routeNotificationForFCM

tusharvikky commented 7 years ago

@enniel It has a comma separated list of tokens. Any info if you have to sent notification to n devices of a single user?

tusharvikky commented 7 years ago

Any update?

enniel commented 7 years ago

Show your code in routeNotificationForFCM and your notification file. I need to test your code.

tusharvikky commented 7 years ago
    public function routeNotificationForFcm()
    {
        $tokens = implode(",", PushToken::where('user_id', $this->id)->pluck('token')->toArray());
        return $tokens;
    } 

Notification File:

<?php

namespace App\Notifications;

use App\Models\PushToken;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use NotificationChannels\FCM\FCMMessage;

class ClassroomCreated extends Notification implements ShouldQueue
{
    use Queueable;

    private $classroom;
    private $tokens;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($classroom)
    {
        $this->classroom = $classroom;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['fcm'];
    }

    public function toFCM($notifiable)
    {
        try {
            // dd($this->classroom);
            $message = Config::get('gb.notification_messages.classroom');
            $rand_message = $message[array_rand($message, 1)];
            return (new FCMMessage())
                // ->to( $this->tokens )
                ->notification([
                    'title' => $rand_message,
                    'body' => $this->classroom->name,
                    'clickAction' => $this->classroom->id
                ]);            
        } catch (\Exception $e) {
                // dd($e);
            Log::error($e);
        }

    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}
enniel commented 7 years ago

You tryed array of tokens?

    public function routeNotificationForFCM()
    {
        return PushToken::where('user_id', $this->id)->pluck('token')->toArray();
    } 
tusharvikky commented 7 years ago

Sadly, that didn't help either.

[2017-05-17 19:29:36] local.ERROR: exception 'NotificationChannels\FCM\Exceptions\CouldNotSendNotification' with message 'Notification was not sent. You should specify device token(s), topic(s) or group(s) for sending notification.' in /<project>/vendor/enniel/laravel-fcm-notification-channel/src/Exceptions/CouldNotSendNotification.php:14
enniel commented 7 years ago

You used routeNotificationForFCM or routeNotificationForFcm method?

tusharvikky commented 7 years ago

Tried w/ both. Didn't work. Still the same.

enniel commented 7 years ago

You can show output from dd(PushToken::where('user_id', $this->id)->pluck('token')->toArray()) ?

tusharvikky commented 7 years ago

image

enniel commented 7 years ago

I'm tried send notification and all works:

// notifiable model
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function routeNotificationForFCM() {
      return ['fYuuanS_YK4:APA91bEsFBKF3cUXotoxvOv2S9kyss9V3ONQZUuDq8cBvm57AuXdJn6SB3sY5JMpe0lLJUPk4D7c8bWTtPLRkwykJNtnazNMmBbo8eoU8mctiTZXf5XvN_lA_h7Mf9o2AUg9gMBgfmKG'];
    }
}
// notification
<?php

namespace App\Notifications;

use NotificationChannels\FCM\FCMMessage;
use Illuminate\Notifications\Notification;

class ExampleNotification extends Notification
{
    public function via($notifiable)
    {
        return ['fcm'];
    }

    public function toFCM($notifiable)
    {
        return (new FCMMessage())
            ->notification([
                'title' => 'Notification title',
                'body' => 'Notification body',
            ]);
    }
}
// send notififications
Notification::send(User::all(), new ExampleNotification());
tusharvikky commented 7 years ago

This is so weird. Only two things different is queue able and that try catch block.

enniel commented 7 years ago

Maybe

    public function routeNotificationForFCM() {
      return PushToken::where('user_id', $this->id)->whereNotNull('token')->pluck('token')->toArray();
    }
enniel commented 7 years ago

You can show your notifiable model code?

tusharvikky commented 7 years ago

Its mostly the same as you have. However, I'm initiating the notification in model boot function.

class Classroom extends Model
{
    use BelongsToTenants;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $guarded = ['id'];
    public $tenantColumns = ['team_id'];

    public static function boot()
    {
        parent::boot();

        // self::creating(function($model){
        //     // ... code here
        // });

        self::created(function($model){
            // Send notification to all User who are member of this team.
            $user_ids = TeamUser::where('team_id', $model->team_id)->pluck('user_id');
            $users = User::whereIn('id', $user_ids)->get();
            // $model->notify(new ClassroomCreated($model));
            Notification::send($users, new ClassroomCreated($model));
        });

        // self::updating(function($model){
        //     // ... code here
        // });

        // self::updated(function($model){
        //     // ... code here
        // });

        // self::deleting(function($model){
        //     // ... code here
        // });

        // self::deleted(function($model){
        //     // ... code here
        // });
    }
enniel commented 7 years ago

Show please User model

tusharvikky commented 7 years ago
<?php

namespace App\Models;

use App\Models\PushToken;
use App\Models\Role;
use App\Models\Team;
use App\Notifications\ResetPassword;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name', 'email', 'password', 'username'];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token'];

    /**
     * Find by Email
     *
     * @param  string $email
     * @return User
     */
    public function findByEmail($email)
    {
        return $this->where('email', $email)->first();
    }

    /**
     * Send the password reset notification.
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPassword($token));
    }

    /**
     * Get the user's first name.
     *
     * @param  string  $value
     * @return string
     */
    public function getNameAttribute($value)
    {
        return ucfirst($value);
    } 

    /**
     * Route notifications for the mail channel.
     *
     * @return string
     */
    public function routeNotificationForFcm()
    {
        $tokens = implode(",", PushToken::where('user_id', $this->id)->pluck('token')->toArray());
        return $tokens;
    } 

    public function routeNotificationForOneSignal()
    {
        $player_ids = implode(",", PushToken::where('user_id', $this->id)->pluck('player_id')->toArray());
        return $player_ids;
    }          
}
enniel commented 7 years ago
    public function routeNotificationForFCM()
    {
        return PushToken::where('user_id', $this->id)->pluck('token')->toArray();
    }
tusharvikky commented 7 years ago

Yes. This isn't the updated code. I'm at office as of now this is the earlier commit. But I assure you the function is the same as you mentioned here.

On Fri 19 May, 2017, 12:44 PM Evgeni Razumov, notifications@github.com wrote:

public function routeNotificationForFCM()    {        return PushToken::where('user_id', $this->id)->pluck('token')->toArray();    }

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/enniel/laravel-fcm-notification-channel/issues/4#issuecomment-302627786, or mute the thread https://github.com/notifications/unsubscribe-auth/ABuiLy9FMt5I62K_VGaFVUWNoHC56fnZks5r7UFEgaJpZM4NaL_6 .

--

Tushar Deo

http://tusharvikky.github.io/

tusharvikky commented 7 years ago
namespace App\Models;

use App\Models\PushToken;
use App\Models\Role;
use App\Models\Team;
use App\Models\UserMeta;
use App\Notifications\ResetPassword;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name', 'email', 'password', 'username'];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token'];

    /**
     * The relations to eager load on every query.
     *
     * @var array
     */
    protected $with = ['roles', 'teams'];

    /**
     * User UserMeta
     *
     * @return Relationship
     */
    public function meta()
    {
        return $this->hasOne(UserMeta::class);
    }

    /**
     * User Roles
     *
     * @return Relationship
     */
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }

    /**
     * Check if user has role
     *
     * @param  string  $role
     * @return boolean
     */
    public function hasRole($role)
    {
        $roles = array_column($this->roles->toArray(), 'name');
        return array_search($role, $roles) > -1;
    }

    /**
     * Teams
     *
     * @return Relationship
     */
    public function teams()
    {
        return $this->belongsToMany(Team::class);
    }

    /**
     * Team member
     *
     * @return boolean
     */
    public function isTeamMember($id)
    {
        $teams = array_column($this->teams->toArray(), 'id');
        return array_search($id, $teams) > -1;
    }

    /**
     * Team admin
     *
     * @return boolean
     */
    public function isTeamAdmin($id)
    {
        $team = $this->teams->find($id);
        if ($team) {
            return (int) $team->user_id === (int) $this->id;
        }
        return false;
    }

    /**
     * Find by Email
     *
     * @param  string $email
     * @return User
     */
    public function findByEmail($email)
    {
        return $this->where('email', $email)->first();
    }

    /**
     * Send the password reset notification.
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPassword($token));
    }

    /**
     * Get the user's first name.
     *
     * @param  string  $value
     * @return string
     */
    public function getNameAttribute($value)
    {
        return ucfirst($value);
    } 

    /**
     * Route notifications for the mail channel.
     *
     * @return string
     */
    public function routeNotificationForFCM()
    {
        // $tokens = implode(",", PushToken::where('user_id', $this->id)->pluck('token')->toArray());
        // dd(PushToken::where('user_id', $this->id)->pluck('token')->toArray());
        return PushToken::where('user_id', $this->id)->whereNotNull('token')->pluck('token')->toArray();
    } 
}
tusharvikky commented 7 years ago

@enniel Any update?

tusharvikky commented 7 years ago

Could you please try with this code:

    public function routeNotificationForFCM() {
      return [ 0 => 'fYuuanS_YK4:APA91bEsFBKF3cUXotoxvOv2S9kyss9V3ONQZUuDq8cBvm57AuXdJn6SB3sY5JMpe0lLJUPk4D7c8bWTtPLRkwykJNtnazNMmBbo8eoU8mctiTZXf5XvN_lA_h7Mf9o2AUg9gMBgfmKG'];
    }
bayuly94 commented 2 years ago

image how to solve it ? i hope add exception and delete failed token

promatik commented 1 year ago

@bayuly94 have you solved your issue? How?