ارسال notification با استفاده از Firebase Cloud Messaging و مدیریت با لاراول

سرویس Firebase Cloud Messaging چیست؟سرویس Firebase Cloud Messaging Platform (با نام قبلی GCM) یک سرویس اعلان رایگان تلفن همراه توسط Google است که توسعه دهندگان برنامه (شخص ثالث) را قادر می سازد اعلان ها را از سرورهای GCM (پیام رسان Google) برای کاربران خود ارسال کنند. ابزاری برای نوشتن یا ساختن درخواست های پیام. Notifications گزینه ای مبتنی بر GUI برای ایجاد درخواست های اعلان ارائه می دهد. برای اتوماسیون کامل و پشتیبانی از انواع پیام ها ، باید درخواست پیام را در یک محیط سرور معتبر ایجاد کنید که از Firebase Admin SDK یا پروتکل های سرور FCM پشتیبانی می کند. این محیط می تواند Cloud Functions برای Firebase ، Google App Engine یا سرور برنامه خود شما باشد.پیام Firebase به شما امکان می دهد notifications را برای همه کاربران خود در هر نقطه از جهان ارسال کنید. در ادامه به آموزش استفاده از این پیام رسان با خواهیم پرداخت.Firebase Cloud Messagingدلایل استفاده از پیام رسان Firebase چیست؟اول ، Google Firebase Messaging Platform چند پلتفرمی است که به طور طبیعی در Firebase که دارای ویژگی های مجموعه طراحی شده برای Android ، iOS و وب تلفن همراه است ، جای می گیرد.دوم ، ارزش اصلی Firebase یکپارچه سازی ویژگی های متقابل است که توانایی ارسال سایر پیام های Firebase به راحتی از طریق FCM است. به عنوان مثال ، می توانید از Firebase Notifications برای ارسال مجدد Chrome push notifications به کاربران خود استفاده کنید.معماری FCMایجاد پروژه در Firebase اولین قدم ایجاد یک پروژه در محیط Google است.توجه: برای گذر از این آموزش ، باید با یک حساب Google وارد سیستم شده باشید که می تواند از کنسول Firebase استفاده کند.شما با کنسول Firebase یک پروژه ایجاد می کنید. کنسول Firebase را باز کنید. روی "ایجاد پروژه جدید" کلیک کنید. (اگر ویژگی های Google غیر از FCM را به پروژه اضافه کرده اید ، می توانید یک پروژه موجود Google را برای پیکربندی FCM وارد کنید.)ایجاد پروژه جدید در firebaseپنجره "ایجاد یک پروژه" باز می شود.اطلاعات زیر را وارد کنید و "ایجاد پروژه" را کلیک کنید.نام پروژهوارد Test شوید. این نام پروژه برنامه شما در کنسول Firebase است.کشور / منطقهانتخاب نام پروژهمرحله دوم ایجاد پروژهانتخاب موقعیت مکانیایجاد پروژه موفقیت آمیزصفحه شروع کنسول Firebase باز می شود.روی "افزودن Firebase به برنامه Android خود" کلیک کنید. (در این مقاله من پروژه اندروید ایجاد میکنم ولی شما میتوانید پلتفرم های دیگر را نیز استفاده کنید.)انتخاب پلتفرم اندرویدصفحه "جزئیات برنامه" باز می شود.نام بسته برنامه تلفن همراه را اینجا وارد کنید. (نام بسته مشخص شده هنگام ایجاد پروژه در Android Studio). این نام ، com.example.test در این آموزش است.اگر فقط از ویژگی FCM استفاده می کنید ، می توانید نام مستعار برنامه و گواهی امضای اشکال زدایی SHA-1 را حذف کنید. در غیر این صورت ، دستورالعمل های روی صفحه را دنبال کنید.پس از مشخص کردن جزئیات برنامه ، روی "افزودن برنامه" کلیک کنید.جزئیات برنامهبا دنبال کردن دستورالعمل های روی صفحه ، پیکربندی را ادامه دهید.صفحه "کپی فایل پیکربندی" به محض باز شدن صفحه ، فایل google-services.json را در دستگاه شما بارگیری می کند. فایل google-services.json را در Android Studio راه اندازی خواهید کرد.دستورالعمل اصلاح فایل build.gradle را نادیده بگیرید زیرا اصلاحاتی که روی صفحه انجام می شود باعث ایجاد خطای ساخت می شود. در مرحله های بعد فایل build.gradle را اصلاح کنید.برای بررسی کلید سرور ، ابتدا "تنظیمات" را از فهرست پروژه انتخاب کنید تا صفحه "تنظیمات" باز شود.تنظیماتبرگه "Cloud Messaging" را در صفحه "تنظیمات" باز کنید.تنظیمات عمومی پروژهدریافت کلید سرور شناسه ارسال کنندهکلید ذخیره شده در سرور برنامه ، کلید سرور است. این کلید سرور دسترسی مجاز به سرویس های Google را برای سرور برنامه فراهم می کند به عنوان یک روش توصیه شده ، هرگز نباید کلید API را در هر کجای کد مشتری خود قرار دهید.رشته ای که به عنوان کلید سرور نمایش داده می شود را در جایی نگه دارید. در مرحله بعدی در زمان استفاده از API برای ارسال notification در پروژه لاراول از آن استفاده خواهیم کرد.برای پیکر بندی این سرویس روی اپلیکشن اندروید خود میتوانید از این منبع استفاده کنید.تفاوت شناسه فرستنده GCM و شناسه فرستنده FCM؟شناسه فرستنده (Google Cloud Messaging (GCM: یک مقدار عددی منحصر به فرد است که هنگام پیکربندی پروژه خود در Google Developers Console / Google Cloud Console ایجاد می شود. شماره پروژه شناسه فرستنده GCM است. در فرآیند ثبت نام برای شناسایی سرور برنامه ای که مجاز به ارسال پیام / اعلان به برنامه کاربر است استفاده می شود.شناسه فرستنده (Firebase Cloud Messaging (FCM: معادل شناسه فرستنده Google Cloud Messaging . در زیر تب Firebase> Project> Settings> Cloud Messaging قابل دسترسی است.سرویس GCM یا FCM؟در حقیقت، FCM نسخه جدید GCM با نام تجاری Firebase است. FCM زیرساخت اصلی GCM را با SDK جدید به ارمغان می آورد تا توسعه پیام ابری را آسان تر کند.بررسی REST API های مهم Firebase Cloud Messagingما در پروژه لاراول برای ارسال notification از API ها استفاده خواهیم کرد به این منظور API های مهم این سرویس را بررسی میکنیم. ارسال notification تکیارسال notification گروهیبررسی اعتبار و صحت FCM registration id (این شناسه در هنگام نصب اپلیکشن برای هر دستگاه ایجاد میشود که سرویس پیام رسان از این شناسه برای ارسال اعلان به آن دستگاه استفاده میکند.)در این آموزش برای آزمایش API ها از Postman استفاده میکنیم.در همه این API ها و برای احراز هویت از کلید سرور که در قسمت قبل بعد از ایجاد پروژه Firebase به دست آوردیم، استفاده میکنیم.1) ارسال notification تکیبرای ارسال notification به یک دستگاه، API ای با این مشخصات و از آدرس https://fcm.googleapis.com/fcm/send برای URL این API استفاده میشود.Headers توجه کنید که با توجه به شکل بالا متد API باید POST باشد. به جای کلید YOUR_API_KEY از کلید سرور خود استفاده کنید. برای body این API به این شکل عمل میکنیم:bodyمتن درخواست باید شامل "notification" و "to" باشد. هیچ محدودیتی در افزودن ویژگی ها به داده json وجود ندارد و میتوانید هر طور که می خواهید کنترل کنید. در قسمت to باید FCM registration id مخصوص دستگاه مورد نظر که میخواهید اعلان را دریافت کند، را وارد میکنید. ارسال اشیا تو در تو نیز ممکن است مانند json زیر:{ &quotnotification&quot:{ &quottitle&quot:&quotNew Text Message&quot, &quotimage&quot:&quothttps://firebase.google.com/images/social.png&quot, &quotmessage&quot:&quotHello how are you?&quot, &quotmeta&quot:{ &quottype&quot:&quotsmall&quot, &quotinfo&quot:&quotSearch&quot } }, &quotto&quot:&quotVALID_REGISTRATION_ID&quot }نتیجه از که در صورت موفقیت آمیز بودن ارسال اعلان مشاهده خواهید کرد به شکل زیر خواهد بود.نتیجه ارسال اعلان موفقیت آمیز2)ارسال notification گروهیبرای ارسال اعلان گروهی میتوانید از URL مربوط به ارسال تکی با متد POST استفاده کنید و body را به شکل زیر بنویسید:bodyدقت کنید که داده های ارسالی را در json مربوط به notification نوشته و FCM registration id های مربوط به دستگاه ها را در آرایه registration_ids قرار دهید.همانند قسمت قبل در بخش notification داده های دیگری نیز میتوانید اضافه کنید.{ &quotregistration_ids&quot: [ &quotVALID_REGISTRATION_ID1&quot, &quotVALID_REGISTRATION_ID2&quot, &quotVALID_REGISTRATION_ID3&quot ], &quotnotification&quot:{ &quottitle&quot:&quottitle of notification&quot, &quotbody&quot:&quotbody of message&quot, &quotimage&quot:&quothttps://firebase.google.com/images/social.png&quot } }بعد از ارسال این API چنین جوابی را دریافت خواهید کرد:پاسخ ارسال گروهی اعلاندر این پاسخ 2 مورد بسیار مهم وجود دارد. اول تعداد اعلان های موفق و ناموفق. همان طور که در شکل مشاهده میکنید، 1اعلان موفق و 2 اعلان ناموفق از 3 اعلان ارسالی داشتیم. دوم نتیجه ارسال اعلان. با توجه به شکل بالا، "VALID_REGISTRATION_ID1" دارای اعتبار بوده و بقیه این شناسه ها فاقد اعتبار هستند.3)بررسی اعتبار و صحت FCM registration idبرای بررسی اعتبار FCM registration id کاربر میتوانید از آدرس <https://iid.googleapis.com/iid/info/<VALID_REGISTRATION_ID برای URL با متد GET به شکل زیر استفاده کنید. توجه داشته باشید که FCM registration id مربوط به کاربر را در URL بالا به جای عبارت <VALID_REGISTRATION_ID> قرار دهید. Headersدر صورت صحت FCM registration id مورد نظر، پاسخ زیر را دریافت خواهید کرد که نمایش دهنده مشخصات اپلیکشن شماست. پاسخ FCM registration id دارای اعتبارمدیریت ارسال Notification با یک سیستم پیاده سازی شده با لاراولدر این قسمت میخواهیم یک سیستم مدیریت برای ارسال اعلان با لاراول پیاده سازی کنیم. در ابتدا یک پروژه لاراول با نام دلخواه ایجاد میکنیم. دستور زیر را در ترمینال خود اجرا کنید تا یک برنامه جدید Laravel ایجاد کنید (ایجاد این پروژه با استفاده از Laravel installer انجام میشود شما میتوانید با composer هم این پروژه را ایجاد کنید):laravel new notification-managementcd notification-managementایجاد پایگاه دادهما برای این پروژه از پایگاه داده My SQL استفاده خواهیم کرد. فایل env. پروژه خود را باز کنید و نام پایگاه داده را انتخاب کنید. برای مثال من نام پایگاه داده را notification انتخاب میکنم.123456DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=notification DB_USERNAME=root DB_PASSWORD=سپس در phpMyAdmin خود یک پایگاه داده خالی با نام notification ایجاد کنید تا جدول های مربوط به پروژه به وسیله migration ها در آن ایجاد شوند.در پستی که قبلا منتشر کرده ام، به طور کامل در مورد migration ها صحبت کرده ام. اگر هنوز آن را مطالعه نکرده اید، می توانید برای فهم بیشتر در مورد Migration ها به آن مراجعه کنید. (مبحث Migration ها در Laravel)برای احراز هویت پروژه، در لاراول 8 نیازی به کد های اضافه نیست و یک سیستم احراز هویت به صورت پیش فرض در زمان ایجاد پروژه روی سیستم موجود است. و migration مربوط به ایجاد جدول کاربران از قبل ایجاد شده (شما میتوانید ستون های این جدول را تغییر دهید.) و فقط برای ایجاد ui های مربوط به صفحه ورود و ثبت نام را میتوانید با اجرای دستور زیر در خط فرمان، ایجاد کنید. (ایجاد و تغییر این صفحات به دلخواه شما خواهد بود و در این مقاله به توضیحات این موارد نمی پردازیم).composer require laravel/ui php artisan ui bootstrap - -authما برای ذخیره کردن اطلاعات دستگاه های کاربران نیز باید جدولی اختصاصی ایجاد کنیم. ارتباط بین جدول های کاربران و دستگاه ها، یک به چند خواهد بود چون ما این مورد را که ممکن است یک کاربر با چند دستگاه از اپلیکشن ما استفاده کند را نیز درنظر میگیریم.برای ایجاد migration برای تولید جدول devices، دستور زیر را در خط فرمان خود وارد کنید.php artisan make:migration create_devices_tableبا اجرای این دستور فایل migration مربوط به جدول devices در مسیر database/migrations ایجاد میشود. به آن پوشه رفته و فایل مربوطه را این طور تغییر دهید:// database/migrations/<timestamp>_create_devices_table.php [...] public function up(){ Schema::create('Devices', function (Blueprint $table) { $table->increments('id'); $table->unsignedBigInteger('user_id')->index(); $table->string('os')->nullable(); $table->string('manufacturer')->nullable(); $table->string('model')->nullable(); $table->string('version')->nullable(); $table->string('versionRelease')->nullable(); $table->string('fcm_reg_id', 191)->unique(); //شناسه ورود کاربر به اپلیکشن شما $table->string('app_version')->nullable(); $table->timestamps(); $table->foreign('user_id')->references('id')->on('users'); }); } [...]در این فایل ستون های مورد نیاز آورده شده است شما بسته به نیاز خود میتوانید آن را تغییر دهید.سپس جدول های مربوط به اعلان ها را میسازیم. برای ایجاد migration برای تولید جدول messages، دستور زیر را در خط فرمان خود وارد کنید.php artisan make:migration create_messages_tableبا اجرای این دستور فایل migration مربوط به جدول messages در مسیر database/migrations ایجاد میشود. به آن پوشه رفته و فایل مربوطه را این طور تغییر دهید:// database/migrations/<timestamp>_create_messages_table.php [...] public function up(){ Schema::create('messages', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('body'); $table->unsignedBigInteger('sender_id'); $table->foreign('sender_id')->references('id')->on('users'); $table->timestamps(); }); } [...]سپس برای ایجاد ارتباط چند به چند بین جدول کاربران و پیام ها باید یک جدول دیگر ایجاد کنیم. ارتباط این 2 جدول چند به چند است به این دلیل که هر پیام را می توان به چند کاربر ارسال کرد و هر کاربر میتواند چند پیام دریافت کرده باشد. برای ایجاد این جدول هم میتوانید در همین فایل Schema مربوط به ایجاد جدول را بنویسید و هم میتوانید یک migration جدید ایجاد کنید.php artisan make:migration create_message_user_tableبا اجرای این دستور فایل migration مربوط به جدول message_user در مسیر database/migrations ایجاد میشود. به آن پوشه رفته و فایل مربوطه را این طور تغییر دهید:// database/migrations/<timestamp>_create_message_user_table.php [...] public function up(){ Schema::create('message_user', function (Blueprint $table) { $table->unsignedBigInteger('message_id')->index(); $table->foreign('message_id')->references('id')->on('messages'); $table->unsignedBigInteger('user_id')->index(); $table->foreign('user_id')->references('id')->on('users'); }); } [...]مدل ها (Model)در این قسمت کلاسی برای دستگاه ها میسازیم و متد های زیر را به آن اضافه میکنیم. برای ساختن مدل برای دستگاه ، دستور زیر را اجرا کنید:php artisan make:model Deviceفایل Device.php را از پوشه App/Models باز کنید و همانند کد های زیر آن را تغییر دهید:<?php namespace App/Models; use Illuminate\Database\Eloquent\Model; class Device extends Model{ /** * The database table used by the model. * * @var string */ protected $table = 'devices'; /** * The database primary key value. * * @var string */ protected $primaryKey = 'id'; /** * Attributes that should be mass-assignable. * * @var array */ protected $fillable = ['user_id' , 'os', 'manufacturer', 'model', 'version', 'versionRelease', 'fcm_reg_id', 'app_version']; public function user(){ return $this->belongsTo('App\Models\User', 'user_id'); } public function messages(){ return $this->belongsToMany('App\Models\Message', 'devicesinfo_message', 'deviceinfo_id', 'message_id'); } }سپس کلاسی برای پیام ایجاد میکنیم و متد های زیر را به آن اضافه میکنیم. برای ساختن مدل برای پیام ، دستور زیر را اجرا کنید:php artisan make:model Messageفایل Message.php را از پوشه App/Models باز کنید و همانند کد های زیر آن را تغییر دهید:<?php namespace App/Models; use Illuminate\Database\Eloquent\Model; class Message extends Model{ /** * The database table used by the model. * * @var string */ protected $table = 'messages'; /** * The database primary key value. * * @var string */ protected $primaryKey = 'id'; /** * Attributes that should be mass-assignable. * * @var array */ protected $fillable = ['title', 'body', 'sender_id']; public function users(){ return $this->belongsToMany('App\Models\User', 'message_user'); } public function sender(){ return $this->belongsTo('App\Models\User', 'sender_id', 'id'); } }ارتباط بین 3 جدول فوق به این صورت است که:کاربرها و دستگاه ها : یک به چند. هر کاربر چند دستگاه میتواند داشته باشد و هر دستگاه فقط مربوط به یک کاربر است.کاربر ها و پیام ها: چند به چند. هر کاربر میتواند چند پیام دریافت کند و هر پیام می تواند به چند کاربر ارسال شود. و در هر مدل ارتباط بین جدول ها را نیز پیاده سازی میکنیم. این متد ها را نیز به مدل User اضافه کنید:public function messages(){ return $this->belongsToMany('App\Models\Message', 'message_user'); } public function devices(){ return $this->hasMany('App\Models\Device'); }ما همچنین با قرار دادن تعدادی از ستون ها در آرایه قابل پر کردن(fillable) برخی از ستون های پایگاه داده خود را به عنوان fillable تعریف کردیم. این به لاراول در مورد مدل ها می گوید: اگر من متد ایجاد(create) یا به روزرسانی(update) را فراخوانی کرده و آرایه ای به عنوان آرگمان فرستادم، فقط ستون هایی که قابلیت fillable را دارند را قبول کن.به این ترتیب ، از سناریویی جلوگیری خواهیم کرد که اگر کاربر بتواند از هر کدام از مرزهای امنیتی ما دور بماند و رکورد مورد نظر خود را برای درج یا به روزرسانی آنها بفرستد، اجازه این کار را نداشته باشد.کنترلر ها(controllers)در این قسمت ما با استفاده از API هایی که در قسمت قبل با آن ها آشنا شدیم، از طریق firebase cloud message به دستگاه هایی که در پایگاه داده ذخیره کردیم اعلان ارسال خواهیم کرد.یک کنترلر به نام MessageController ایجاد کنید تا در آن متد های مربوط به مدیریت اعلان را پیاده سازی کنیم. به این منظور دستور زیر را در خط فرمان اجرا کنید:php artisan make:Controller MessageControllerسپس فایل MessageController.php ایجاد شده در مسیر App/Http/Controllers را این گونه تغییر دهید:<?php namespace App\Http\Controllers; use App\Device; use App\Http\Controllers\Controller; use App\Message; use App\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class MessageController extends Controller{ /*این متد برای نمایش لیست پیام های ارسال شده اخیر تنظیم شده است که شامل بخش جست و جو بر اساس عنوان و متن پیام نیز هست. */ public function index(Request $request){ $perPage = 25; $query = Message::orderby(&quotid&quot, &quotdesc&quot); //filters $keyword = $request->get('search'); if (!empty($keyword)) { $query->where(function ($query) use ($keyword) { $query->where('title', 'LIKE', &quot%$keyword%&quot) ->orWhere('body', 'LIKE', &quot%$keyword%&quot); }); } $messages = $query->paginate($perPage); return view('messages.index', compact('messages')); } /*این متد به منظور نمایش فرم ارسال پیام میباشد. برای نمایش تعداد کاربرانی که پیام را دریافت خواهد کرد، ما تعداد را نیز به صفحه نمایش فرم ارسال میکنیم. */ public function create(){ $allUsersCount = User::count(); return view('messages.create', compact('allUsersCount')); } /*این متد به منظور ارسال پیام میباشد*/ public function store(Request $request){ /*اول قوانینی که ورودی این متد باید از آن پیروی کند را پیاده سازی میکنیم*/ $request->validate([ 'title' => 'required', 'body' => 'required', 'users_id' => 'array|required' ],[ 'title.required' => 'وارد کردن عنوان برای پیام الزامیست.', 'body.required' => 'وارد کردن متن پیام الزامیست.', 'users_id.required' => 'هیچ کاربری برای ارسال انتخاب نکردید!', ]); $users = $request->users_id; $tokens = []; /* ابتدا پیام ارسالی را در جدول ذخیره میکنیم.*/ $message = Message::create([ 'title' => $request->title, 'body' => $request->body, 'sender_id' => Auth::id() ]); /*برای ارسال به تمام دستگاه های داخل پایگاه داده باید ستون مربوط به شناسه ورود کاربر به اپلیکشن را دریافت کرده و به عنوان گیرنده وارد کنیم. */ $query = Device::select('id', 'fcm_reg_id', 'user_id'); $tokens = $query->pluck('fcm_reg_id')->all(); //آرایه شناسه دریافت کنندگان $user_ids = $query->pluck('user_id')->all();//آرایه شناسه کاربران دستگاه های دریافت کننده $message->users()->sync(array_filter($user_ids));//در این خط جدول شناسه ها را همگام سازی میکنیم. $data = [ //APIداده هایی فرستاده شده در بدنه &quotregistration_ids&quot => $tokens, &quotnotification&quot => [ &quottitle&quot => $request->title, &quotbody&quot => $request->body, &quotsound&quot => &quotdefault&quot ] ]; $dataString = json_encode($data); $headers = [ //سربرگ API 'Authorization: key=' . env('SERVER-KEY'), //توضیح در ادامه 'Content-Type: application/json', ]; //API ارسال $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $dataString); $response = curl_exec($ch); //API پاسخ curl_close ( $ch ); $failure = json_decode($response)->failure; //تعداد ارسال های ناموفق } $msg = &quotپیام با موفقیت ارسال شد. تعداد ارسال ناموفق: &quot. $failure; return redirect('/messages')->with('success', $msg); } /*در این متد لیست افرادی که پیام را دریافت کردند را نمایش میدهیم.*/ public function show(Request $request, $id){ $message = Message::find($id); $query = $message->users(); //filters $keyword = $request->get('search'); if (!empty($keyword)) { $query->where(function ($query) use ($keyword) { $query->where('name', 'LIKE', &quot%$keyword%&quot) ->orWhere('phone', 'LIKE', &quot%$keyword%&quot); }); } $users = $query->paginate(25); return view('messages.show', compact('users')); } }شما میتوانید متد های فوق را بر حسب نیاز خود تغییر دهید.برای احراز هویت برای API بخش Firebase همان طور که در قسمت قبل گفته شد، کلید سرور را به عنوان کلید احراز هویت باید در سربرگ بفرستیم ولی برای حفظ امنیت آن کد و به دلیل استفاده مکرر در بخش های دیگر، این کلید را در فایل env. با عنوان SERVER-KEY قرار میدهیم و به این شکل از آن استفاده میکنیم:. env('SERVER-KEY')مسیر ها (Routes)برنامه ما تقریباً آماده است حال مسیرهایی را برای دسترسی به تمام صفحاتی که تاکنون ایجاد کرده ایم تعریف می کنیم. فایل routes/web.php را باز کنید و موارد زیر را اضافه کنید:Route::resource('messages' ,'MessageController');ویو ها (views)شما میتوانید به صورت دلخواه view های مدیریت پیام خود را بسازید. فقط به این نکته توجه کنید که کل فایل های blade مربوط به پیام را در پوشه ای به نام messages قرار دهید. چون در کنترلر این گونه آدرس دهی شده است. اگه پوشه بندی دیگری را نظر گرفتید آن را در کنترلر ها هم تنظیم کنید.اجرای پروژهحال میتوانید با دستورphp artisan serveپروژه خود را اجرا کرده و در آدرس http://localhost:8000مشاهده کنید.نکته مهمدر مورد این که چه طور fcm_reg_id مربوط به دستگاه های کاربران اپلیکشن خود را چگونه ذخیره کنید، پیشنهاد میکنم با توجه به API هایی که اپلیکشن خود را به سرور و پنل مدیریت خود مرتبط میکنید، پیاده سازی کنید. برای مثال میتوانید API ای پیاده سازی کنید تا در زمان ورود و احراز هویت در اپلیکشن، اطلاعات مربوط به دستگاهی که اپلیکشن بر روی آن نصب شده را به سرور منتقل کرده و ذخیره کنید.امیدوارم مطالب ارائه شده برای شما مفید واقع شده باشد. مراجع: https://docs.kii.com | https://www.izooto.com | https://medium.com