زیرساخت فنی وب پوش؛ Service Worker، اشتراک، VAPID و FCM
وبپوش زمانی قابل اتکا است که چهار مرحله جداگانه درست کار کنند: کاربر با رضایت خود اشتراک بسازد، مرورگر آن را از طریق سرویسورکر دریافت کند، سرور پیام را به سرویس پوش برساند و دستگاه اعلان را طبق محدودیتهای سیستم نمایش دهد. پاسخ موفق ارسال فقط پذیرش درخواست را نشان میدهد و نه نمایش قطعی یا خواندهشدن پیام.
در این مقاله:
- معماری وبپوش و مرز مسئولیتها
- HTTPS، مجوز و چرخه عمر اشتراک
- endpoint، رمزنگاری، VAPID و اعتبارنامه FCM
- سرویسورکر، نمایش اعلان و اجرای پسزمینه
- TTL، آفلاینبودن و پیامهای قابل جایگزینی
- نگهداری، عیبیابی و استفاده از پوشفا
در این مقاله، مسیر فنی وبپوش و نکات نگهداری آن را بررسی میکنیم؛ از تفاوت Push API با مسیر FCM تا انقضای اشتراک، TTL، امنیت کلیدها و این واقعیت که سرویسورکر یک فرایند دائماً در حال اجرا نیست.
معماری وبپوش و مرز مسئولیتها
در مسیر استاندارد وبپوش، صفحه وب مجوز اعلان را از کاربر میگیرد و یک اشتراک پوش ایجاد میکند. این اشتراک معمولاً شامل یک endpoint، یعنی نشانی سرویس دریافتکننده، و اطلاعاتی برای رمزگشایی پیام است. سرور برنامه payload را با سازوکار استاندارد رمزگذاری میکند و آن را به endpoint میفرستد. سرویس پوش پیام را به مرورگر میرساند و سرویسورکر رویداد را پردازش میکند.
هر جزء پاسخگوی بخش متفاوتی است:
| جزء | مسئولیت | نمونه بررسی |
|---|---|---|
| صفحه وب | توضیح ارزش عضویت و گرفتن رضایت | وضعیت مجوز و نتیجه ثبت |
| سرویسورکر | دریافت رویداد، نمایش و کلیک | مسیر فایل، scope و خطای اجرا |
| سرور برنامه | انتخاب مخاطب، ساخت پیام و ثبت نتیجه | شناسه پیام و لاگ تلاش ارسال |
| سرویس پوش | انتقال پیام در شبکه پوش | پذیرش، رد یا خطای موقت |
| سیستمعامل و مرورگر | اعمال مجوزها و تنظیمات اعلان | کانال اعلان، حالت تمرکز و محدودیت باتری |
در پیادهسازی مستقیم Push API، قرارداد PushSubscription با توکن FCM یکی نیست. پوشفا از FCM استفاده میکند و توکنهای مشترکان را در مسیر خود نگهداری میکند؛ بنابراین کد عمومی Web Push یا یک توکن متعلق به پروژه دیگر را نباید بدون تطبیق با مسیر پوشفا به کار برد. برای آشنایی مقدماتی با ثبت اشتراک، میتوانید راهنمای عضویت و دریافت وبپوش را نیز ببینید.
HTTPS، مجوز و چرخه عمر اشتراک
برای استفاده معمول از Push API، سایت باید روی HTTPS اجرا شود؛ استثنای رایج، محیط محلی توسعه است. HTTPS فقط برای ارسال امن اطلاعات نیست؛ مرورگر از آن برای اعتماد به مبدأ، سرویسورکر و عملیات اشتراک استفاده میکند. فایل سرویسورکر نیز باید از مبدأ مناسب و با پاسخ واقعی JavaScript ارائه شود، نه با صفحه ورود یا HTML خطا.
درخواست مجوز را پس از توضیح روشن و در واکنش به اقدام مستقیم کاربر نمایش دهید؛ برای مثال، کاربر روی «برای موجودشدن کالا خبرم کن» کلیک کند. مجوز مجاز به معنی ثبت موفق اشتراک در سرور نیست و باید نتیجه ثبت را جداگانه ذخیره و بررسی کنید. اگر کاربر مجوز را مسدود کرده است، تکرار مداوم درخواست راهی برای دورزدن انتخاب او نیست.
- وضعیت مجوز و پشتیبانی مرورگر را بررسی کنید.
- سرویسورکر را با scope درست ثبت کنید.
- اشتراک موجود را بخوانید و فقط در صورت نیاز اشتراک تازه بسازید.
- اشتراک را به حساب، مخاطب یا alias درست متصل کنید.
- در بازگشت کاربر، تغییر توکن یا اشتراک را دوباره همگام کنید.
- اشتراکهایی را که سرویس پوش نامعتبر اعلام میکند، از صف ارسال کنار بگذارید.
یک کاربر ممکن است روی چند مرورگر یا دستگاه چند اشتراک داشته باشد؛ پس تعداد اشتراکها برابر با تعداد افراد نیست. هنگام خروج از حساب، تغییر مالک دستگاه یا حذف دادههای مرورگر، اتصال شناسه کاربر به اشتراک را نیز بازبینی کنید. این کار از ارسال پیام شخصی به کاربر بعدی دستگاه جلوگیری میکند.
در iOS و iPadOS، وباپی که به صفحه اصلی اضافه شده است شرایط متفاوتی از یک تب عادی دارد. در نسخههای 16.4 به بعد، درخواست مجوز پوش برای وباپ صفحه اصلی و پس از اقدام مستقیم کاربر امکانپذیر است؛ جزئیات را در توضیح WebKit درباره وبپوش در iOS و iPadOS بررسی کنید.
endpoint، رمزنگاری، VAPID و اعتبارنامه FCM
endpoint نشانی اختصاصی مسیر دریافت است و باید مانند داده حساس عملیاتی نگهداری شود. در کنار آن، اطلاعات رمزنگاری اشتراک برای رمزگشایی محتوای پیام به کار میرود. کلیدهای رمزنگاری هر اشتراک با کلیدهای احراز هویت فرستنده یکی نیستند؛ این دو را در مدل داده، تنظیمات و مستندات داخلی جدا نگه دارید.
VAPID روشی برای معرفی سرور ارسالکننده در Web Push استاندارد است. کلید عمومی آن میتواند در فرایند اشتراک به کار رود، اما کلید خصوصی باید فقط روی سرور باقی بماند. در مسیر FCM، اعتبارنامههای سرویس پروژه برای ارتباط سرور با FCM استفاده میشوند. بنابراین VAPID و اعتبارنامه سرویس FCM جایگزین یکدیگر نیستند و نباید نام آنها در تنظیمات یا کد بهجای هم استفاده شود.
- کلید خصوصی VAPID، کلید خصوصی سرویس و کلیدهای API را در مرورگر یا اپلیکیشن موبایل قرار ندهید.
- کلیدها را در مخزن عمومی، لاگ، ابزار تحلیل سمت کاربر یا نشانی URL ثبت نکنید.
- ثبت endpoint را با احراز مالکیت، کنترل نرخ و اعتبارسنجی ورودی محافظت کنید.
- برای درخواستهایی که از مرورگر به سرور میرسند، کنترل نشست و محافظت CSRF را متناسب با معماری بررسی کنید.
- محتوای حساس را در متن اعلان یا پارامترهای قابل مشاهده لینک قرار ندهید.
در پروژهای که از پوشفا استفاده میکند، کلید عمومی سرویس برای راهاندازی سمت کلاینت است؛ کلید خصوصی سرویس فقط باید در محیط سرور بماند. یک endpoint یا شناسه مشترک را نیز بهتنهایی مجوز ارسال برای هر کاربر فرض نکنید و سطح دسترسی آن را در سامانه خود کنترل کنید.
سرویسورکر، نمایش اعلان و اجرای پسزمینه
سرویسورکر یک برنامه دائماً روشن نیست. مرورگر آن را هنگام رویدادهایی مانند دریافت پوش فعال میکند و پس از پایان کار میتواند متوقفش کند. بنابراین نباید وبپوش را کانال اجرای دائمی پردازشهای پسزمینه، زمانبندی دقیق یا همگامسازی نامحدود بدانید. کارهای ناهمگام مربوط به رویداد باید در محدوده همان رویداد کامل شوند.
در پیادهسازی مستقیم، سرویسورکر معمولاً payload را میخواند و با showNotification اعلان را نمایش میدهد. خطای تبدیل payload، تصویر نامعتبر یا مقصد کلیک را ثبت کنید و برای حالت ناقص، عنوان و متن ساده جایگزین داشته باشید. در مسیر FCM، رفتار پیامهای notification و data در حالت foreground و background یکسان نیست؛ اگر SDK و کد سفارشی هر دو اعلان بسازند، نتیجه میتواند دو اعلان برای یک پیام باشد. مالک نمایش را برای هر نوع پیام مشخص کنید.
در WebKit، نمایش قابل مشاهده اعلان بخشی از الزامات وبپوش است؛ بنابراین طراحی خود را بر «پوش بیصدا و نامرئی» بنا نکنید. کار پسزمینه را فقط به اندازه لازم و با توجه به محدودیت مرورگر انجام دهید. اعلان نمایشدادهشده نیز ثابت نمیکند انسان آن را خوانده است؛ گزارش نمایش، در صورت فعالبودن مسیر گزارش، فقط یک مرحله فنی از زنجیره تحویل است.
| رویداد | معنای قابل اتکا | ادعایی که نباید از آن نتیجه گرفت |
|---|---|---|
| پذیرش ارسال | درخواست در مسیر ارسال پذیرفته شده است | رسیدن به دستگاه |
| نمایش موفق | نمایش اعلان در مسیر قابل گزارش ثبت شده است | خواندن پیام توسط انسان |
| کلیک | تعامل با اعلان ثبت شده است | خرید یا تکمیل هدف کسبوکار |
TTL، آفلاینبودن و پیامهای قابل جایگزینی
TTL یا زمان اعتبار پیام مشخص میکند پیام در زمان آفلاینبودن دستگاه تا چه مدت میتواند برای تحویل نگه داشته شود. TTL تضمین تحویل، زمان دقیق نمایش یا ذخیرهسازی نامحدود نیست. پس از پایان TTL، پیام منقضی میشود؛ حتی اگر کاربر بعداً به شبکه برگردد. اشتراک منقضی یا نامعتبر نیز موضوعی جدا از TTL است.
برای یک پیشنهاد دو ساعته، نگهداری پیام برای چند روز منطقی نیست. در مقابل، برای اطلاعرسانیای که پس از چند ساعت هنوز ارزش دارد، بازه مناسبتری انتخاب میشود. این تصمیم باید بر اساس عمر واقعی محتوا، نه صرفاً بیشترین مقدار ممکن، انجام شود.
در برخی مسیرهای FCM، پیامهای قابل ادغام برای وضعیتهایی مانند «آخرین قیمت» یا «آخرین وضعیت سفارش» کاربرد دارند؛ اما ادغام در صف انتقال با جایگزینشدن اعلان نمایشدادهشده یکی نیست. تنظیمات و رفتار پلتفرمها متفاوت است. برای رسیدهای مستقل یا رویدادهای حسابداری، حذف پیام قبلی ممکن است اطلاعات لازم را از بین ببرد.
ارسال مجدد را با تأخیر افزایشی، تصادفیسازی محدود و رعایت راهنمای سرویس انجام دهید. timeout همیشه به معنی نرسیدن درخواست نیست؛ تکرار بیمحاسبه میتواند پیام تکراری بسازد. شناسه پایدار رویداد، زمان ارسال و نتیجه هر تلاش را ذخیره کنید تا تشخیص تکرار ممکن باشد. توضیح عملیتر درباره پیامهای آفلاین و TTL در راهنمای وبپوش در حالت آفلاین آمده است.
نگهداری، عیبیابی و استفاده از پوشفا
اشتراک نامعتبر بخشی طبیعی از چرخه عمر وبپوش است: کاربر ممکن است مجوز را لغو کند، دادههای مرورگر را پاک کند، مرورگر یا دستگاه را تغییر دهد یا توکن تازهای دریافت کند. وقتی سرویس ارسال نامعتبرشدن اشتراک را تأیید کرد، آن را از ارسالهای بعدی حذف یا غیرفعال کنید؛ retry نامحدود فقط صف و هزینه پردازش را بزرگتر میکند. هنگام بازگشت کاربر، اشتراک فعلی را دوباره با مخاطب یا alias او تطبیق دهید.
پوشفا از FCM، topic، توکنهای ذخیرهشده، alias، گزارش تحویل و کلیک و APIهای سرور پشتیبانی میکند. برای راهاندازی SDK، کلید عمومی سرویس و فایل ریشه pushfa-messaging-sw.js را از پنل همان سرویس دریافت و نصب کنید و کد دقیق نمایشدادهشده در پنل را مبنا قرار دهید؛ نام بسته، تابع یا قطعهکد حدسی را جایگزین آن نکنید. کلید خصوصی و اطلاعات محرمانه باید در سرور بمانند.
- در محیط آزمایشی، ثبت اشتراک، دریافت در حالت باز و پس از بستن صفحه را روی دستگاه واقعی بررسی کنید.
- مجوز مسدود، قطع شبکه، توکن نامعتبر، TTL کوتاه و تنظیمات اعلان سیستم را جداگانه آزمایش کنید.
- در Android، مجوز اعلان و کانال اعلان را جدا از مجوز وب بررسی کنید؛ کاربر میتواند کانال را مستقل خاموش کند.
- پذیرش ارسال، نمایش، کلیک و تبدیل را در گزارشهای جداگانه تحلیل کنید.
- شناسه پیام و نتیجه تلاش را لاگ کنید، اما endpoint کامل، توکن و کلید خصوصی را در لاگ عمومی ننویسید.
- افت تحویل را به تفکیک مرورگر، سیستمعامل، نسخه سرویسورکر و نوع پیام بررسی کنید؛ میانگین کل میتواند مشکل یک پلتفرم را پنهان کند.
اگر اعلان ارسال میشود اما به مقصد نمیرسد، ابتدا تفاوت پذیرش ارسال و نمایش را روشن کنید، سپس مجوز، نسخه worker، اعتبار اشتراک، TTL، تنظیمات دستگاه و نوع پیام را بهترتیب بررسی کنید. برای این سناریو، راهنمای عیبیابی دریافتنشدن پوش مکمل این مقاله است.
آیا بستهبودن صفحه یعنی سرویسورکر همیشه آماده است؟
خیر. مرورگر میتواند سرویسورکر را فقط هنگام رویداد فعال کند و سپس متوقف سازد. دریافت پوش به بازبودن همان تب وابسته نیست، اما به پشتیبانی مرورگر، اتصال، مجوزها و محدودیتهای سیستم وابسته است.
آیا VAPID همان کلید سرویس FCM است؟
خیر. VAPID برای معرفی فرستنده در Web Push استاندارد است و اعتبارنامه FCM برای ارتباط سرور با FCM به کار میرود. این دو را باید در مسیر فنی و تنظیمات جدا نگه داشت.
آیا TTL تحویل پیام را تضمین میکند؟
خیر. TTL فقط بازه اعتبار نگهداری پیام برای تحویل احتمالی در زمان آفلاینبودن است و تضمین نمایش، خواندهشدن یا تحویل صددرصدی نیست.