لماذا دليل آخر؟
عندما تم تكليفي بإعداد مسودة إشعارات الدفع ، أظهر بحث سريع أن هناك بالفعل الكثير من المقالات حول إعداد إشعارات الدفع على المحور. هنا هي الأنسب ، في رأيي:
كيف يعمل JS: إخطارات الويبإعلامات الويب PUSH سريعة وسهلة 924 /عمال الخدمة. دفع الويب وأين يعيشونكل هذا على ما يرام ، لكنني شخصيًا افتقرت حقًا إلى دليل بسيط ومفهوم يسمح لي على الفور ، عمليًا عن طريق النسخ واللصق ، بجعل كل شيء يعمل على الفور. حسنًا ، بالإضافة إلى ذلك ، من بين الكتيبات ، لا يوجد ثعبان مصمم للدعم.
استغرق إعداد الإشعارات في النهاية ثلاثة أيام ويبدو لي أن هذا كثير جدًا. نأمل أن تساعد مقالتي شخصًا ما على إعداد الإشعارات في غضون ثلاث ساعات بدلاً من ثلاثة أيام.
يتم تنفيذ المشروع الذي أعمل عليه في Django وسأصف تقدم العمل فيما يتعلق بهذا الإطار ، ولكن أولئك الذين يرغبون يمكنهم تكييفه بسهولة مع Flask أو أي شيء آخر.
لذا ، دعنا نذهب.
نحصل على المفاتيح
بدون مفاتيح ، بطبيعة الحال ، لن يسمحوا لنا بأي مكان ، لذلك دعونا نبدأ معهم. لتوليد المفاتيح ، استخدمت
py_vapid . يتم تثبيته تلقائيًا مع
pywebpush ، والذي سنظل بحاجة إليه لاحقًا ، لذا لتجنب الاستيقاظ مرتين ، سنبدأ بـ pywebpush:
> bin/pip install pywebpush < > > bin/vapid --applicationServerKey No private_key.pem file found. Do you want me to create one for you? (Y/n)Y Generating private_key.pem Generating public_key.pem Application Server Key = < Server Key>
تمت إضافة قيمة مفتاح خادم التطبيق الناتجة إلى ملف settings.py.
NOTIFICATION_KEY = < Server Key>
بالإضافة إلى ذلك ، سنحتاج إلى تمرير NOTIFICATION_KEY إلى السياق. أسهل طريقة للقيام بذلك هي كتابة
معالج السياق الخاص بك .
جعل عامل الخدمة
عامل خدمة ، لا يعرف - هذا ملف خاص يعمل في الخلفية. نحتاجه لعرض إخطاراتنا.
يبدو أبسط كود عامل الخدمة كما يلي:
self.addEventListener('push', function(event) { var message = JSON.parse(event.data.text());
والآن نحن بحاجة إلى تسجيل عامل الخدمة لدينا. العملية ، من حيث المبدأ ، موصوفة
هنا . لذلك ، باختصار:
function checkWorkerAndPushManager () { if (!('serviceWorker' in navigator)) { console.log('Workers are not supported.'); return; } if (!('PushManager' in window)) { console.log('Push notifications are not supported.'); return; } } function registerWorker () { window.addEventListener('load', function () { navigator.serviceWorker.register('/static/js/sw.js').then(function (registration) { console.log('ServiceWorker registration successful'); }, function (err) { console.log('ServiceWorker registration failed: ', err); return; }); }); return true; } var supported = checkWorkerAndPushManager(); if (supported){ var worker = registerWorker (); }
عظيم ، يمكنك التحقق من عمل عامل الخدمة لدينا. للقيام بذلك ، انتقل إلى أدوات المطور في متصفح ، وتأكد من ظهور رسالة على وحدة التحكم حول التسجيل الناجح للويكر وانتقل إلى علامة التبويب التطبيق وحدد Service Worker على اليسار.

إذا لم يظهر الإشعار ، فتحقق من تمكين الإشعارات في متصفحك.
حسنًا ، نحن نعلم بالفعل كيفية إرسال الإشعارات لأنفسنا. رائع ، دعنا ننتقل.
احصل على إذن المستخدم لإظهار الإخطارات
بعد تسجيل Woker ، اطلب من المستخدم الإذن لإظهار الإخطارات.
function requestPermission() { return new Promise(function(resolve, reject) { const permissionResult = Notification.requestPermission(function(result) {
لا توجد تعليقات مطلوبة لهذا الرمز ، فهو يعمل فقط.
اشترك واحفظ اشتراكك
الاشتراك هو أيضا في المقدمة.
يمكنك العثور على رمز الاشتراك هنا ، ولكن لا توجد وظيفة urlBase64ToUint8Array مستخدمة ، لذا أقوم بالتشفير معها.
NOTIFICATION_KEY = '{{ NOTIFICATION_KEY }}; function urlBase64ToUint8Array(base64String) { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) .replace(/\-/g, '+') .replace(/_/g, '/') ; const rawData = window.atob(base64); return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0))); } function subscribeUserToPush(key) { return navigator.serviceWorker.register('/static/path/to/js/sw.js') .then(function(registration) { var subscribeOptions = { userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(key), }; return registration.pushManager.subscribe(subscribeOptions) }) .then(function(pushSubscription) { sendSubscriptionToBackEnd(pushSubscription); }); }
(ربما يكون عنوان urlBase64ToUint8Array المستخدم هنا من فئة العكازات والدراجات ، لكن محاولة تحويل البيانات باستخدام btoa لم تنجح ، ولا أعرف السبب. ربما سيخبرك أحدهم).
ثم نرسل البيانات المستلمة إلى الخادم. لقد نفذت مثل هذا:
function sendSubscriptionToBackEnd(subscription) { $.post( SAVE_REGISTRATION_URL, { 'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
حسنا ، ثم نقوم بحفظ هذا على الخادم. يمكنك حق الخط. نعم ، لا تحاول إنشاء علاقة اشتراك مستخدم واحد لواحد. يبدو أن الأمر واضح ، ولكن فجأة قد يرغب أي شخص.
لقد استخدمت مثل هذا النموذج البسيط للحفظ ، سيتم استخدامه لاحقًا ، لذلك سأعطيه:
class UserSubscription(models.Model): subscription = models.CharField(max_length=500) user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='subscriptions')
الخطوة الأخيرة. إرسال رسالة باستخدام pywebpush
كل شيء موجود في البرنامج التعليمي ، لا يوجد خفايا خاصة. حسنًا ، باستثناء أن الرسالة مصنوعة في مثل هذا الهيكل بحيث يمكن لعامل الخدمة لدينا تحليلها.
import json from pywebpush import webpush, WebPushException from django.conf import settings from .models import UserSubscription def push_notification(user_id): user_subscriptions = UserSubscription.objects.filter(user_id=notification.user_id) for subscription in user_subscriptions: data = json.dumps({ 'title': 'Hello', 'body': 'there', }) try: webpush( subscription_info=json.loads(subscription.subscription), data=data, vapid_private_key='./private_key.pem', vapid_claims={ 'sub': 'mailto:{}'.format(settings.ADMIN_EMAIL), } ) notification.sent = True notification.save() except WebPushException as ex: print('I\'m sorry, Dave, but I can\'t do that: {}'.format(repr(ex))) print(ex)
في الواقع ، يمكنك بالفعل استدعاء إشعار الدفع من غلاف django ومحاولة البدء.
في هذا الكود ، سيكون من الجيد اعتراض الرد بالحالة 410. مثل هذه الإجابة تقول أنه تم إلغاء الاشتراك ، وسيكون من الجيد حذف هذه الاشتراكات من قاعدة البيانات.
في الختام
في الواقع ، هناك
مكتبة django-webpush رائعة أخرى. ربما أولئك الذين يعملون مع Django يجب أن يبدأوا به.
يوم سعيد مبرمج PS!