- klen.github.io
- Введение
- Получение и конвертация сертификата
- Реализация IOS Push в python-приложениях
- Интеграция с Django
- Apple push notifications python
- Apple push notifications python
- Настраиваем Web Push Notifications использованием pywebpush шаг за шагом
- Зачем еще одно руководство?
- Получаем ключи
- Делаем Service worker
- Получаем разрешение пользователя на показ уведомлений
- Подписываемся и сохраняем подписку
- Последний шаг. Отправляем сообщение с помощью pywebpush
- В заключение
klen.github.io
Я уже писал статью про реализацию Push уведомлений с использованием сервиса Urbanairship. У этого способа есть ряд преимуществ и недостатков. Преимущества я описал в вышеприведенной статье, недостаки сервиса в его лимитах на количество бесплатных сообщений и периодических отключениях на техническое обслуживание.
Сегодня мы рассмотрим реализацию IOS Push уведомлений своими руками для Python программ.
Введение
IOS Push уведомления бывают двух видов: локальные и удаленные. Локальные инициируются приложением на стороне клиента и в данной статье не рассматриваются. Удаленные уведомления отсылаются со стороны сервера на клиентское приложение при помощи службы APNS (Apple Push Notification Service). Процесс выглядит следующим образом:
- Приложение регистрируется в APNS и получает Device Token;
- Приложение сообщает Device Token нашему серверу;
- Теперь сервер может установить SSL соединение с APNS и отправить Push уведомление;
Получение и конвертация сертификата
Push сертификаты для приложений можно получить на iOS Provisioning Portal.
Выберите свое приложение и зайдите в раздел настроек: Configure.
Скачайте production и development сертификаты ( *.cer). Возможно вам потребуется предварительно включить Push нотификации для своего приложения и создать их.
Дальнейшие действия лучше провести на компьютере с OSX. Импортируйте полученные сертификаты и экспортируйте их в формате p12. Вероятно вам потребуется ключ разработчика с которым были созданы CSR запросы.
Полученный файл в формате p12 необходимо переконвертировать в pem. Для этой задачи я написал простенький shell скрипт.
Сконвертируем с его помощью полученный от Apple Dev сертификат в нужный нам формат:
В процессе у вас будет запрошен пароль на сертификаты, если они создавались без пароля, просто нажмите Enter . Результатом этой операции будут pem файлы с теми же названиями.
Этим же скриптом их можно протестировать, что в дальнейшем избавит от множества проблем при отладке:
Если соединение сразу сбрасывается или выводятся SSL ошибки, вы что-то сделали неправильно.
Реализация IOS Push в python-приложениях
В своих проектах я использую PyAPNs библиотеку. Простой файл обвязка вокруг нее реализует все основные задачи: push.py
Вполне возможно, что токен от приложения будет приходить к вам в формате Base64, тогда перед сохранением необходимо проделать следующие преобразования.
Интеграция с Django
При интеграции с Django проектом необходимо подумать о переключении между developer и production и об асинхронности запросов в APNS.
Асинхронность достигается использованием Celery.
Стоит подумать и об отключении неактивных устройств: tasks.py:
Написать функцию для асинхронной broadcast рассылки сообщений множеству клиентов, предлагается для самостоятельного написания в качестве домашнего задания.
Источник
Apple push notifications python
A Python library for interacting with the Apple Push Notification service (APNs)
Either download the source from GitHub or use easy_install:
Apple recommends to query the feedback service daily to get the list of device tokens. You need to create a new connection to APNS to see all the tokens that have failed since you only receive that information upon connection. Remember, once you have viewed the list of tokens, Apple will clear the list from their servers. Use the timestamp to verify that the device tokens haven’t been reregistered since the feedback entry was generated. For each device that has not been reregistered, stop sending notifications. By using this information to stop sending push notifications that will fail to be delivered, you reduce unnecessary message overhead and improve overall system performance.
For more complicated alerts including custom buttons etc, use the PayloadAlert class. Example:
To send custom payload arguments, pass a dictionary to the custom kwarg of the Payload constructor.
Enhanced Message with immediate error-response
Send a notification. note that identifer is the information to indicate which message has error in error-response payload, it should be UNIQUE since PyAPNs will also use it to determine the range of messages to be re-sent.
Error response worker will be auto-close after 30 secs idle of connection operations. If you want disable APNS connection and error-responses handler immediately, force_close it.
Extra log messages when error-response occur, auto-resent afterwards.
- Currently support single notification only
- Async response of error response and response time varies from 0.1
0.8 secs by observation
- Non-blocking ssl socket connection to send notification without waiting for response.
- A separate thread for constantly checking error-response from read connection.
- A sent notification buffer used for re-sending notification that were sent after failed notification, or arbitrary connection close by apns.
- Reference to non-blocking apns pull request by minorblend, enhanced message by hagino3000
- Send notification at throughput of 1000/secs
- In worse case of when 1st notification sent failed, error-response respond after 1 secs and 999 notification sent are discarded by APNS at the mean time, all discarded 999 notifications will be resent without loosing any of them. With the same logic, if notification resent failed, it will resent rest of resent notification after the failed one.
Источник
Apple push notifications python
A minimal Django app that implements Device models that can send messages through APNS, FCM/GCM, WNS and WebPush.
The app implements four models: GCMDevice , APNSDevice , WNSDevice and WebPushDevice . Those models share the same attributes:
- name (optional): A name for the device.
- active (default True): A boolean that determines whether the device will be sent notifications.
- user (optional): A foreign key to auth.User, if you wish to link the device to a specific user.
- device_id (optional): A UUID for the device obtained from Android/iOS/Windows APIs, if you wish to uniquely identify it.
- registration_id (required): The FCM/GCM registration id or the APNS token for the device.
The app also implements an admin panel, through which you can test single and bulk notifications. Select one or more FCM/GCM, APNS, WNS or WebPush devices and in the action dropdown, select «Send test message» or «Send test message in bulk», accordingly. Note that sending a non-bulk test message to more than one device will just iterate over the devices and send multiple single messages. UPDATE_ON_DUPLICATE_REG_ID: Transform create of an existing Device (based on registration id) into a update. See below Update of device with duplicate registration ID for more details.
- Python 3.6+
- Django 2.2+
- For the API module, Django REST Framework 3.7+ is required.
- For WebPush (WP), pywebpush 1.3.0+ is required (optional). py-vapid 1.3.0+ is required for generating the WebPush private key; however this step does not need to occur on the application server.
- For Apple Push (APNS), apns2 0.3+ is required (optional).
You can install the library directly from pypi using pip:
Edit your settings.py file:
If you need to support multiple mobile applications from a single Django application, see Multiple Application Support for details.
If you are planning on running your project with APNS_USE_SANDBOX=True , then make sure you have set the development certificate as your APNS_CERTIFICATE . Otherwise the app will not be able to connect to the correct host. See settings for details.
For more information about how to generate certificates, see docs/APNS.
You can learn more about APNS certificates here.
Native Django migrations are in use. manage.py migrate will install and migrate all models.
All settings are contained in a PUSH_NOTIFICATIONS_SETTINGS dict.
In order to use FCM/GCM, you are required to include FCM_API_KEY or GCM_API_KEY . For APNS, you are required to include APNS_CERTIFICATE . For WNS, you need both the WNS_PACKAGE_SECURITY_KEY and the WNS_SECRET_KEY .
General settings
- USER_MODEL : Your user model of choice. Eg. myapp.User . Defaults to settings.AUTH_USER_MODEL .
- UPDATE_ON_DUPLICATE_REG_ID : Transform create of an existing Device (based on registration id) into a update. See below Update of device with duplicate registration ID for more details.
- UNIQUE_REG_ID : Forces the registration_id field on all device models to be unique.
APNS settings
- APNS_CERTIFICATE : Absolute path to your APNS certificate file. Certificates with passphrases are not supported. If iOS application was build with «Release» flag, you need to use production certificate, otherwise debug. Read more about Generation of an APNS PEM file.
- APNS_AUTH_KEY_PATH : Absolute path to your APNS signing key file for Token-Based Authentication . Use this instead of APNS_CERTIFICATE if you are using .p8 signing key certificate.
- APNS_AUTH_KEY_ID : The 10-character Key ID you obtained from your Apple developer account
- APNS_TEAM_ID : 10-character Team ID you use for developing your company’s apps for iOS.
- APNS_TOPIC : The topic of the remote notification, which is typically the bundle ID for your app. If you omit this header and your APNs certificate does not specify multiple topics, the APNs server uses the certificate’s Subject as the default topic.
- APNS_USE_ALTERNATIVE_PORT : Use port 2197 for APNS, instead of default port 443.
- APNS_USE_SANDBOX : Use ‘api.development.push.apple.com’, instead of default host ‘api.push.apple.com’. Default value depends on DEBUG setting of your environment: if DEBUG is True and you use production certificate, you should explicitly set APNS_USE_SANDBOX to False.
FCM/GCM settings
- FCM_API_KEY : Your API key for Firebase Cloud Messaging.
- FCM_POST_URL : The full url that FCM notifications will be POSTed to. Defaults to https://fcm.googleapis.com/fcm/send.
- FCM_MAX_RECIPIENTS : The maximum amount of recipients that can be contained per bulk message. If the registration_ids list is larger than that number, multiple bulk messages will be sent. Defaults to 1000 (the maximum amount supported by FCM).
- FCM_ERROR_TIMEOUT : The timeout on FCM POSTs.
- GCM_API_KEY , GCM_POST_URL , GCM_MAX_RECIPIENTS , GCM_ERROR_TIMEOUT : Same parameters for GCM
WNS settings
- WNS_PACKAGE_SECURITY_KEY : TODO
- WNS_SECRET_KEY : TODO
Источник
Настраиваем Web Push Notifications использованием pywebpush шаг за шагом
Зачем еще одно руководство?
Когда передо мной поставили задачу сделать черновой вариант push notifications, быстрый поиск показал, что на хабре уже есть много статей по настройке push notifications. Вот наиболее, на мой взгляд, годные:
Это все прекрасно, но лично мне очень не хватало простого и понятного руководства, которое позволило бы сразу, практически методом копипаста сделать так, чтобы все сразу заработало. Ну и кроме того среди руководств нет адаптированного под бек на питоне.
Настройка уведомлений в итоге заняла три дня и мне кажется, что это несколько многовато. Надеюсь, моя статья поможет кому-то настроить push notifications за три часа вместо трех дней.
Проект, на котором я работаю, реализован на Django и описывать ход работы я буду применительно к этому фреймворку, но желающие легко адаптируют его к Flask или чему-либо еще.
Получаем ключи
Без ключей нас, естественно, никуда не пустят, поэтому начнем с них. Для генерации ключей я использовала py_vapid. Он устанавливается автоматически вместе с pywebpush, который нам все равно понадобится позже, поэтому мы, чтобы два раза не вставать, начнем с pywebpush:
Полученное значение Application Server Key добавляем в файл settings.py.
Кроме того, нам нужно будет передать NOTIFICATION_KEY в контекст. Проще всего для этого написать свой context_processor.
Делаем Service worker
Service worker, кто не знает — это специальный файл, работающий в фоновом режиме. Нам он нужен для отображения наших уведомлений.
Самый простой код service worker будет выглядеть так:
А теперь нам нужно зарегистрировать наш service worker. Процесс, в принципе, описан здесь. Поэтому кратко:
Отлично, можно проверить работу нашего service worker. Для этого зайдите в Developer Tools в браузере, убедитесь, что в консоли появилось сообщение об успешной регистрации вокера и перейдите на вкладку Application и слева выберите Service Worker.
Если уведомление не появляется — проверьте, что у вас в браузере разрешены уведомления.
Ну вот, мы уже умеем оправлять уведомления сами себе. Круто, едем дальше.
Получаем разрешение пользователя на показ уведомлений
После того, как вокер зарегистрирован, попросим у пользователя разрешение показывать уведомления.
К этому коду и комментариев никаких не нужно, он просто работает.
Подписываемся и сохраняем подписку
Подписка выполняется тоже на фронте. Здесь можно найти код подписки, но нет используемой функции urlBase64ToUint8Array, поэтому я код вместе с ней.
(Используемая здесь urlBase64ToUint8Array, видимо, из разряда костылей и велосипедов, но попытка перекодировать данные с помощью btoa не привела к успеху, уж не знаю, почему. Может кто подскажет).
Далее полученные данные отправляем на сервер. У меня это реализовано так:
Ну и дальше сохраняем это на сервере. Можно прямо строкой. Да, не вздумайте делать связь user-subscription типа «один к одному». Вроде бы очевидно, но вдруг кому вздумается.
У меня для сохранения используется вот такая простая модель, она дальше будет использоваться, поэтому я ее приведу:
Последний шаг. Отправляем сообщение с помощью pywebpush
Здесь все по туториалу, никаких особенных тонкостей. Ну, разве что сообщение делаем такой структуры, чтобы наш service worker мог его разобрать.
Собственно, уже можно вызывать push_notification из django shell и пытаться запустить.
В этом коде хорошо бы еще сделать перехват ответа со статусом 410. Такой ответ говорит, что подписка аннулирована, и такие подписки хорошо бы удалять из БД.
В заключение
На самом деле есть еще одна замечательная библиотека django-webpush. Возможно, тем, кто работает с Django, стоит начинать именно с нее.
Источник