لإرسال رسائل فورية، يجب أولاً الحصول على إذن من المستخدم ثم الاشتراك في خدمة إرسال الرسائل الفورية على جهازه. يتضمّن ذلك استخدام JavaScript API للحصول على كائن PushSubscription، ثم إرساله إلى الخادم.
تتولّى JavaScript API إدارة هذه العملية بشكل مباشر. يوضّح هذا الدليل المسار الكامل، بما في ذلك رصد الميزات وطلب الإذن وإدارة عملية الاشتراك.
رصد الميزات
في البداية، تحقَّق مما إذا كان المتصفّح يتيح تلقّي الرسائل الفورية. يمكنك التحقّق من توفّر ميزة الإشعارات الفورية من خلال إجراء عمليتَي تحقّق:
- ابحث عن
serviceWorkerفي العنصرnavigator. - ابحث عن
PushManagerفي العنصرwindow.
if (!('serviceWorker' in navigator)) {
// Service Worker isn't supported on this browser, disable or hide UI.
return;
}
if (!('PushManager' in window)) {
// Push isn't supported on this browser, disable or hide UI.
return;
}
على الرغم من أنّ توافق المتصفّح مع كلّ من عامل الخدمة والرسائل الفورية يتزايد، احرص دائمًا على رصد كلتا الميزتين وتحسين تطبيقك تدريجيًا.
تسجيل مشغّل الخدمات
بعد رصد الميزات، ستعرف أنّ عاملي الخدمة وإرسال الرسائل الفورية متاحان. بعد ذلك، سجِّل مشغّل الخدمات.
عند تسجيل عامل خدمة، تخبر المتصفّح بموقع ملف عامل الخدمة. الملف هو ملف JavaScript، ولكن يمنحه المتصفّح إذن الوصول إلى واجهات برمجة تطبيقات مشغّل الخدمات، بما في ذلك الرسائل الفورية. على وجه التحديد، يشغّل المتصفّح الملف في بيئة عامل الخدمة.
لتسجيل عامل خدمة، استدعِ navigator.serviceWorker.register() ومرِّر المسار إلى ملفك. على سبيل المثال:
function registerServiceWorker() {
return navigator.serviceWorker
.register('/service-worker.js')
.then(function (registration) {
console.log('Service worker successfully registered.');
return registration;
})
.catch(function (err) {
console.error('Unable to register service worker.', err);
});
}
تُعلِم هذه الدالة المتصفّح بموقع ملف عامل الخدمة. في هذا المثال، يقع ملف عامل الخدمة في /service-worker.js. بعد طلب register()، ينفّذ المتصفّح الخطوات التالية:
نزِّل ملف عامل الخدمة.
شغِّل JavaScript.
إذا تم تشغيل الملف بشكل صحيح بدون أخطاء، سيتم حلّ الوعد الذي تم إرجاعه بواسطة
register(). في حال حدوث أخطاء، يتم رفض الوعد.
ملاحظة: إذا تم رفض register()، راجِع JavaScript بحثًا عن أخطاء إملائية أو أخطاء أخرى في "أدوات مطوّري البرامج في Chrome".
عندما يتم حلّ register()، يتم عرض ServiceWorkerRegistration. يمكنك استخدام هذا التسجيل للوصول إلى PushManager API.
توافُق متصفّح PushManager API
طلب الإذن
بعد تسجيل عامل الخدمة والحصول على الإذن، احصل على إذن من المستخدم لإرسال رسائل فورية.
واجهة برمجة التطبيقات للحصول على الإذن بسيطة. ومع ذلك، تم مؤخرًا تغيير واجهة برمجة التطبيقات من تلقّي دالة ردّ الاتصال إلى عرض Promise. وبما أنّه لا يمكنك تحديد إصدار واجهة برمجة التطبيقات الذي يستخدمه المتصفّح، عليك تنفيذ الإصدارَين والتعامل معهما.
function askPermission() {
return new Promise(function (resolve, reject) {
const permissionResult = Notification.requestPermission(function (result) {
resolve(result);
});
if (permissionResult) {
permissionResult.then(resolve, reject);
}
}).then(function (permissionResult) {
if (permissionResult !== 'granted') {
throw new Error("We weren't granted permission.");
}
});
}
في الرمز السابق، يؤدي طلب Notification.requestPermission() إلى عرض طلب للمستخدم:

بعد أن يتفاعل المستخدم مع طلب الإذن من خلال النقر على السماح أو الحظر أو إغلاقه، ستتلقّى النتيجة كسلسلة: 'granted' أو 'default' أو 'denied'.
في نموذج الرمز البرمجي، يتم حلّ الوعد الذي تعرضه askPermission() في حال منح الإذن، وإلا سيتم عرض خطأ ورفض الوعد.
تعامَل مع حالة الاستخدام الحدّي التي ينقر فيها المستخدم على الزر حظر. في هذه الحالة، لا يمكن لتطبيق الويب أن يطلب الإذن من المستخدم مرة أخرى. على المستخدم إزالة حظر تطبيقك يدويًا من خلال تغيير حالة الإذن في لوحة الإعدادات. يجب التفكير مليًا في وقت وكيفية طلب الإذن، لأنّه إذا نقر المستخدم على حظر، لن يكون من السهل التراجع عن هذا القرار.
يمنح معظم المستخدمين الإذن إذا فهموا سبب طلب التطبيق له.
يوضّح هذا المستند كيف تطلب بعض المواقع الإلكترونية الشائعة الإذن في وقت لاحق.
الاشتراك في خدمة الإشعارات باستخدام PushManager
بعد تسجيل عامل الخدمة والحصول على الإذن، يمكنك الاشتراك في خدمة المستخدم من خلال استدعاء registration.pushManager.subscribe().
function subscribeUserToPush() {
return navigator.serviceWorker
.register('/service-worker.js')
.then(function (registration) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
),
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(function (pushSubscription) {
console.log(
'Received PushSubscription: ',
JSON.stringify(pushSubscription),
);
return pushSubscription;
});
}
عند استدعاء الطريقة subscribe()، يمكنك تمرير عنصر options يتألف من مَعلمات مطلوبة واختيارية.
يوضّح هذا القسم الخيارات التي يمكنك تمريرها.
خيارات userVisibleOnly
عندما تمت إضافة ميزة الرسائل الفورية إلى المتصفحات لأول مرة، لم يكن المطوّرون متأكدين من إمكانية إرسال رسائل فورية بدون عرض إشعار. يُشار إلى ذلك عادةً باسم الإشعارات الصامتة لأنّ المستخدم لا يعرف أنّه قد وقع حدث في الخلفية.
كان مصدر القلق هو إمكانية تتبُّع المطوّرين لموقع المستخدم الجغرافي بشكل مستمر بدون علمه.
لتجنُّب هذا السيناريو والسماح لمؤلفي المواصفات بتحديد أفضل طريقة لإتاحة هذه الميزة، تمت إضافة الخيار userVisibleOnly. إنّ تمرير القيمة true هو اتفاق رمزي مع المتصفّح على أنّ تطبيق الويب يعرض إشعارًا في كل مرة يتلقّى فيها رسالة دفع (أي بدون دفع صامت).
يجب تمرير القيمة true. إذا لم تضمِّن مفتاح userVisibleOnly أو تمرِّر false، ستتلقّى الخطأ التالي:
Chrome currently only supports the Push API for subscriptions that will result
in user-visible messages. You can indicate this by calling
`pushManager.subscribe({userVisibleOnly: true})` instead. See
[https://goo.gl/yqv4Q4](https://goo.gl/yqv4Q4) for more details.
يتيح Chrome استخدام Push API فقط للاشتراكات التي تؤدي إلى ظهور رسائل للمستخدمين. يمكنك الإشارة إلى ذلك من خلال الاتصال بالرقم pushManager.subscribe({userVisibleOnly: true}). لمزيد من المعلومات، يُرجى الانتقال إلى https://goo.gl/yqv4Q4.
يبدو أنّه لن يتم تنفيذ الإشعارات الصامتة الشاملة في Chrome. بدلاً من ذلك، يستكشف مؤلفو المواصفات واجهة برمجة تطبيقات للميزانية تتيح لتطبيقات الويب إرسال عدد معيّن من الرسائل الفورية الصامتة استنادًا إلى استخدام تطبيق الويب.
الخيار applicationServerKey
كان هذا المستند يشير سابقًا إلى مفاتيح خادم التطبيق. تستخدم خدمة الإشعارات الفورية مفاتيح خادم التطبيق لتحديد التطبيق الذي يشترك فيه المستخدم ولضمان أن يرسل التطبيق نفسه رسائل إلى هذا المستخدم.
مفاتيح خادم التطبيق هي زوج من المفاتيح العامة والخاصة الفريدة لتطبيقك. عليك الحفاظ على سرية المفتاح الخاص لتطبيقك، ومشاركة المفتاح العام بحرية.
إنّ الخيار applicationServerKey الذي تم تمريره إلى طلب subscribe() هو المفتاح العام لتطبيقك. يمرّر المتصفّح هذا المفتاح إلى خدمة الإشعارات الفورية عند اشتراك المستخدم، ما يتيح لخدمة الإشعارات الفورية ربط المفتاح العام لتطبيقك بـ PushSubscription الخاص بالمستخدم.
يوضّح الرسم البياني التالي هذه الخطوات.
- حمِّل تطبيق الويب في متصفّح واستدعِ الدالة
subscribe()، مع تمرير مفتاح خادم التطبيق العام. - بعد ذلك، يرسل المتصفّح طلب شبكة إلى خدمة الإشعارات الفورية، التي تنشئ نقطة نهاية وتربطها بالمفتاح العام لتطبيقك وتعيد نقطة النهاية إلى المتصفّح.
- يضيف المتصفّح نقطة النهاية هذه إلى
PushSubscription، التي يعرضها الوعدsubscribe().
عند إرسال رسالة دفعية، أنشئ عنوان Authorization يحتوي على معلومات موقّعة باستخدام المفتاح الخاص لخادم تطبيقك. عندما تتلقّى خدمة الإشعارات الفورية طلبًا بإرسال إشعار فوري، فإنّها تتحقّق من صحة عنوان التفويض الموقّع هذا من خلال البحث عن المفتاح العام المرتبط بنقطة النهاية التي تتلقّى الطلب. إذا كان التوقيع صالحًا، ستعرف خدمة الإشعارات الفورية أنّ الطلب وارد من خادم التطبيق الذي يتضمّن المفتاح الخاص المطابق. هذا إجراء أمان يمنع الآخرين من إرسال رسائل إلى مستخدمي تطبيقك.
من الناحية الفنية، يكون applicationServerKey اختياريًا. ومع ذلك، يتطلّب أبسط تنفيذ على Chrome ذلك، وقد تتطلّبه المتصفّحات الأخرى في المستقبل. وهي اختيارية في Firefox.
يحدّد مواصفات VAPID مفتاح خادم التطبيق. عندما ترى إشارات إلى مفاتيح خادم التطبيق أو مفاتيح VAPID، تذكَّر أنّها متطابقة.
إنشاء مفاتيح خادم التطبيق
يمكنك إنشاء مجموعة من مفاتيح خادم التطبيق العامة والخاصة من خلال الانتقال إلى web-push-codelab.glitch.me أو باستخدام سطر الأوامر web-push لإنشاء المفاتيح على النحو التالي:
$ npm install -g web-push
$ web-push generate-vapid-keys
أنشئ هذه المفاتيح مرة واحدة فقط لتطبيقك، وتأكَّد من الحفاظ على سرية المفتاح الخاص.
الأذونات وsubscribe()
للدالة subscribe() تأثير جانبي واحد. إذا لم يكن تطبيق الويب يملك الإذن بعرض الإشعارات عند الاتصال بـ subscribe()، سيطلب المتصفّح الأذونات نيابةً عنك. يكون هذا الخيار مفيدًا إذا كانت واجهة المستخدم تعمل مع هذا المسار، ولكن إذا كنت تريد المزيد من التحكّم (وهو ما يريده معظم المطوّرين)، استخدِم واجهة برمجة التطبيقات Notification.requestPermission() التي تم تناولها في هذا المستند سابقًا.
نظرة عامة على PushSubscription
تتصل بالدالة subscribe()، وتمرّر الخيارات، وتتلقّى وعدًا يتم تنفيذه إلى PushSubscription. على سبيل المثال:
function subscribeUserToPush() {
return navigator.serviceWorker
.register('/service-worker.js')
.then(function (registration) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
),
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(function (pushSubscription) {
console.log(
'Received PushSubscription: ',
JSON.stringify(pushSubscription),
);
return pushSubscription;
});
}
يحتوي الكائن PushSubscription على جميع المعلومات المطلوبة لإرسال رسائل فورية إلى هذا المستخدم. إذا طبعت المحتوى باستخدام JSON.stringify()، سيظهر لك ما يلي:
{
"endpoint": "https://some.pushservice.com/something-unique",
"keys": {
"p256dh":
"BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
"auth":"FPssNDTKnInHVndSTdbKFw=="
}
}
endpoint هو عنوان URL لخدمة الإشعارات الفورية. لتفعيل رسالة الإشعارات الفورية، أرسِل طلب POST إلى عنوان URL هذا.
يحتوي العنصر keys على القيم المستخدَمة لتشفير بيانات الرسائل المُرسَلة مع رسالة الدفع. (يتناول هذا المستند موضوع تشفير الرسائل لاحقًا).
إرسال اشتراك إلى الخادم
بعد الحصول على اشتراك الإشعارات الفورية، أرسِله إلى الخادم. يمكنك تحديد طريقة إرسالها، ولكن ننصحك باستخدام JSON.stringify() لاستخراج جميع البيانات اللازمة من عنصر الاشتراك. يمكنك بدلاً من ذلك تجميع النتيجة نفسها يدويًا، على سبيل المثال:
const subscriptionObject = {
endpoint: pushSubscription.endpoint,
keys: {
p256dh: pushSubscription.getKeys('p256dh'),
auth: pushSubscription.getKeys('auth'),
},
};
// The above is the same output as:
const subscriptionObjectToo = JSON.stringify(pushSubscription);
لإرسال الاشتراك من صفحة الويب، استخدِم ما يلي:
function sendSubscriptionToBackEnd(subscription) {
return fetch('/api/save-subscription/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(subscription),
})
.then(function (response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function (responseData) {
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
يتلقّى خادم Node.js هذا الطلب ويحفظ البيانات في قاعدة بيانات لاستخدامها لاحقًا.
app.post('/api/save-subscription/', function (req, res) {
if (!isValidSaveRequest(req, res)) {
return;
}
return saveSubscriptionToDatabase(req.body)
.then(function (subscriptionId) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({data: {success: true}}));
})
.catch(function (err) {
res.status(500);
res.setHeader('Content-Type', 'application/json');
res.send(
JSON.stringify({
error: {
id: 'unable-to-save-subscription',
message:
'The subscription was received but we were unable to save it to our database.',
},
}),
);
});
});
باستخدام تفاصيل PushSubscription على خادمك، يمكنك إرسال رسالة إلى المستخدم في أي وقت.
إعادة الاشتراك بانتظام لتجنُّب انتهاء الصلاحية
عند الاشتراك في خدمة تلقّي الإشعارات الفورية، غالبًا ما تتلقّى PushSubscription.expirationTime من null. من الناحية النظرية، يعني هذا أنّ الاشتراك لا تنتهي صلاحيته أبدًا. (في المقابل، يشير DOMHighResTimeStamp إلى وقت انتهاء الصلاحية الدقيق). ومع ذلك، تسمح المتصفّحات عادةً بانتهاء صلاحية الاشتراكات. على سبيل المثال، يمكن أن يحدث ذلك إذا لم يتم تلقّي إشعارات فورية لفترة طويلة، أو إذا رصد المتصفّح أنّ المستخدم لا يستخدِم تطبيقًا لديه إذن بإرسال إشعارات فورية. إحدى الطرق لمنع حدوث ذلك هي إعادة اشتراك المستخدم عند تلقّي كل إشعار، كما يوضّح المقتطف التالي. ويتطلّب ذلك إرسال إشعارات بشكل متكرّر بما يكفي لمنع المتصفّح من انتهاء صلاحية الاشتراك تلقائيًا. عليك الموازنة بعناية بين مزايا الحاجة المشروعة إلى الإشعارات وعيوب إرسال رسائل غير مرغوب فيها إلى المستخدمين بشكل غير طوعي فقط لمنع انتهاء صلاحية الاشتراك. في النهاية، يجب عدم محاولة التحايل على جهود المتصفّح لحماية المستخدم من اشتراكات الإشعارات التي نسيها منذ فترة طويلة.
/* In the Service Worker. */
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
// Display notification or handle data
// Example: show a notification
const title = 'New Notification';
const body = 'You have new updates!';
const icon = '/images/icon.png';
const tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
// Attempt to resubscribe after receiving a notification
event.waitUntil(resubscribeToPush());
});
function resubscribeToPush() {
return self.registration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription.unsubscribe();
}
})
.then(function() {
return self.registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
});
})
.then(function(subscription) {
console.log('Resubscribed to push notifications:', subscription);
// Optionally, send new subscription details to your server
})
.catch(function(error) {
console.error('Failed to resubscribe:', error);
});
}
الأسئلة الشائعة
في ما يلي بعض الأسئلة الشائعة:
هل يمكن تغيير خدمة الإشعارات الفورية التي يستخدمها المتصفّح؟
لا، يختار المتصفّح خدمة الإشعارات الفورية. كما هو موضّح في هذا المستند بشأن طلب subscribe()، يرسل المتصفّح طلبات شبكة إلى خدمة الإشعارات الفورية لاسترداد التفاصيل التي تشكّل PushSubscription.
هل تستخدم خدمات الإشعارات الفورية المختلفة واجهات برمجة تطبيقات مختلفة؟
تتوقّع جميع خدمات الإشعارات الفورية استخدام واجهة برمجة التطبيقات نفسها.
تصف واجهة برمجة التطبيقات الشائعة هذه، والتي تُعرف باسم بروتوكول الإشعارات الفورية على الويب، طلب الشبكة الذي يقدّمه تطبيقك لتفعيل رسالة فورية.
إذا اشتركت في قناة من الكمبيوتر، هل سيتم الاشتراك فيها أيضًا من الهاتف؟
لا، يجب أن يسجّل المستخدم لتلقّي الرسائل الفورية على كل متصفّح يريد تلقّي الرسائل عليه. ويتطلب ذلك أيضًا أن يمنح المستخدم الإذن على كل جهاز.
الخطوات التالية
- نظرة عامة على الإشعارات الفورية على الويب
- طريقة عمل الرسائل الفورية
- الاشتراك في قناة مستخدم
- تجربة المستخدم المتعلقة بالأذونات
- إرسال الرسائل باستخدام مكتبات الإشعارات الفورية على الويب
- بروتوكول Web Push
- التعامل مع أحداث الإشعارات الفورية
- عرض إشعار
- طريقة عمل الإشعارات
- أنماط الإشعارات الشائعة
- الأسئلة الشائعة حول الإشعارات الفورية
- المشاكل الشائعة والإبلاغ عن الأخطاء