{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "В наушниках по жизни: заметки с тегом PHP",
    "_rss_description": "Здесь я пишу свои идеи, мысли, описываю события своей жизни и просто делаю личные и рабочие заметки. «А Вы что, собираетесь жить вечно?»",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/alexbirukov.ru\/?go=tags\/php\/",
    "feed_url": "https:\/\/alexbirukov.ru\/?go=tags%2Fphp%2Fjson%2F",
    "icon": "https:\/\/alexbirukov.ru\/pictures\/userpic\/userpic@2x.jpg?1683051473",
    "authors": [
        {
            "name": "Бирюков Александр",
            "url": "https:\/\/alexbirukov.ru\/",
            "avatar": "https:\/\/alexbirukov.ru\/pictures\/userpic\/userpic@2x.jpg?1683051473"
        }
    ],
    "items": [
        {
            "id": "326",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/php-server-dlya-rassylki-push-na-android-i-ios\/",
            "title": "PHP сервер для рассылки Push на Android и iOS",
            "content_html": "<p>Долгое время искал в интернете нормальное решение для массовой рассылки Push сообщений на Android и iOS, но ничего подходящего и нормально работающего не попадалось.<\/p>\n<p>В Delphi долгое время приходилось использовать компоненты Kinvey (или Pasre). При этом возникали новые проблемы зависимости от платформы, ключей и пр. С любым серьёзным изменением приходилось изменять, как сам проект, так и настройки проекта. В некоторых случаях сторонние компоненты отказывались работать на той или иной платформе по не понятной причине. А так же, огромным минусом Kinvey, было то, что при получении Push сообщения на iOS не воспроизводилось звуковое уведомление. В конце концов, зависимость от третьей стороны всегда является определённым минусом любого проекта.<\/p>\n<p>И вот после очередных поисков я объединил все имеющиеся знания и сделал серверную часть для регистрации устройств и рассылки Push сообщений.<\/p>\n<p>Принцип работы скрипта достаточно прост. В нём имеются функции для регистрации (удаления) токенов устройств, ну и собственно сами функции рассылки. Большая часть мануалов? которые мне удалось найти были написаны либо неправильно, либо попросту были неполными.<\/p>\n<h2>Введение<\/h2>\n<p>Немного теории. Для отправки Push сообщений используются сервисы <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/NetworkingInternet\/Conceptual\/RemoteNotificationsPG\/Chapters\/ApplePushService.html\">APNS<\/a> у Apple и <a href=\"http:\/\/developer.android.com\/google\/gcm\/index.html\">GCM<\/a> у Google. Наш скрипт может выступать в качестве самостоятельного сервера рассылки Push через сервера Apple и Google, а так же принимать токены устройств регистрируемых в базе данных.<\/p>\n<h2>Apple, iOS и ApnsPHP<\/h2>\n<p>Начнём с более сложной части.<br \/>\nЯ не стану изобретать велосипед и воспользуюсь уже имеющимися в сети, бесплатными, библиотеками написанными на PHP. Набор библиотек ApnsPHP представляет собой набор классов для работы с Push сообщениями APNS. Скачать их с примерами можно на GitHub по <a href=\"https:\/\/github.com\/immobiliare\/ApnsPHP\/tree\/master\/ApnsPHP\">ссылке<\/a>.<\/p>\n<p>Но одних библиотек нам мало. Самое сложное, это генерация и конвертирование сертификатов для работы с Push на iOS. Я опишу полный алгоритм экспорта и конвертации сертификатов, а затем их дальнейшее применение в скриптах.<\/p>\n<h3>Генерация сертификата для отправки Push сообщений<\/h3>\n<p>Будем предполагать, что вы уже создали и настроили сертификаты в личном кабинете разработчика и загрузили их в «Связку ключей» на ваш Mac.<\/p>\n<ol start=\"1\">\n<li>Запускаем утилиту <b>«Связка ключей»<\/b> и в левой части выбираем раздел <b>«Мои сертификаты»<\/b>.<\/li>\n<li>Раскрываем сертификат интересующего нас проекта. <b>БУДЬТЕ ВНИМАТЕЛЬНЫ!<\/b> Есть две версии сертификатов, <b>Developer<\/b> (используется при отладке и разработке) и <b>Production<\/b> (используется для рабочей версии). Выбираем сертификат и закрытый ключ данного сертификата.<\/li>\n<li>Нажимаем правой кнопкой и выбираем пункт «Экспортировать объектов: 2». Сохраняем полученные сертификаты. Я сохранил с именами <i><b>server_certificates_bundle_sandbox.p12<\/b><\/i> (для сертификата разработки) и <i><b>server_certificates_bundle_prod.p12<\/b><\/i> (для сертификата публикации). <b>Внимание!<\/b> При экспорте поле пароля оставляем пустым. В дальнейшем вы сможете усложнить систему защиты и выгрузить сертификаты с указанием пароля.<\/li>\n<\/ol>\n<p>Для подтверждения валидности сертификатов пользователя которые мы только что получили, необходим корневой сертификат. Для получения корневого сертификата необходимо выполнить следующие действия:<\/p>\n<ol start=\"1\">\n<li>Переходим на <a href=\"https:\/\/www.entrust.net\/downloads\/root_index.cfm\">сайт загрузки корневых сертификатов<\/a>.<\/li>\n<li>Выбираем <b>«Personal Use and Secure Server Installation»<\/b> и нажимаем кнопку <b>«Download Certificates»<\/b>.<\/li>\n<li>Нажимаем на <b>«Root Certificates»<\/b>.<\/li>\n<li>Нас интересуют два сертификата <b>«entrust_ssl_ca.cer»<\/b> и <b>«entrust_2048_ca.cer»<\/b>. Скачиваем их. Вообще, в изначальном описании написано, что сертификат «entrust_ssl_ca.cer» используется в <b>Prodution<\/b> режиме, а «entrust_2048_ca.cer» в режиме <b>Development<\/b>. Но есть пометка, что после 22 декабря 2010 в качестве Production сертификата так же можно использовать «entrust_2048_ca.cer». <b><i>Т. е. данный сертификат можно использовать в обоих режимах работы, меняя лишь сертификаты пользователя<\/i><\/b>.<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain.png\" width=\"1280\" height=\"1024\" alt=\"Открываем \"Связку ключей\"\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain-2.png\" width=\"1280\" height=\"1024\" alt=\"Экспортируем сертификаты\" \/>\n<\/div>\n<\/div>\n<p>Далее, нам необходимо открыть скачанные сертификаты на Mac’е, т. е. импортировать их в «Связку ключей». Для этого просто делаем двойной клик на каждом сертификате.<\/p>\n<ol start=\"1\">\n<li>Открываем в левой части <b>«Связки ключей»<\/b> раздел <b>«Вход»<\/b> («Сертификаты»).<\/li>\n<li>Находим наш сертификат и экспортируем его <b>«entrust_root_certification_authority_2048.pem»<\/b>.<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain3.png\" width=\"1280\" height=\"1024\" alt=\"Открываем корневой сертификат.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain4.png\" width=\"1280\" height=\"1024\" alt=\"Экспортируем сертификат.\" \/>\n<\/div>\n<\/div>\n<p>На данный момент, мы получили 3 основных файла для работы с сервисом APNS:<\/p>\n<ul>\n<li><b>«entrust_root_certification_authority_2048.pem»<\/b> — корневой сертификат.<\/li>\n<li><b>«server_certificates_bundle_sandbox.p12»<\/b> — сертификат пользователя для режима Development.<\/li>\n<li><b>«server_certificates_bundle_prod.p12»<\/b> — сертификат пользователя для режима Production.<\/li>\n<\/ul>\n<p>Как можно заметить, сертификаты пользователя имеют расширение *.p12, но для работы нам необходимы файлы формата *.pem.<\/p>\n<p>Для конвертации я воспользовался бесплатным набором утилит <a href=\"https:\/\/slproweb.com\/products\/Win32OpenSSL.html\">OpenSSL для Windows<\/a>.<br \/>\nПосле установки пакета, для простоты выполнения команд я использовал TotalCommander.<\/p>\n<ol start=\"1\">\n<li>Открываем в левой части каталог установленного OpenSSL и переносим туда наши сертификаты.<\/li>\n<li>В нижней части TotalCommander в командной строке выполняем следующие команды:<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">openssl pkcs12 -in server_certificates_bundle_sandbox.p12 -out server_certificates_bundle_sandbox.pem -nodes -clcerts\nopenssl pkcs12 -in server_certificates_bundle_prod.p12 -out server_certificates_bundle_prod.pem -nodes -clcerts<\/code><\/pre><p>На запрос ввода пароля, просто нажимаем Enter.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert.png\" width=\"1280\" height=\"1024\" alt=\"Подготавливаем сертификаты и программу.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert2.png\" width=\"1280\" height=\"1024\" alt=\"Сертификаты.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert4.png\" width=\"1280\" height=\"1024\" alt=\"Выполнение команд конвертации сертификатов.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert5.png\" width=\"1280\" height=\"1024\" alt=\"Просто нажимаем Enter.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert3.png\" width=\"1280\" height=\"1024\" alt=\"Готовые сертификаты.\" \/>\n<\/div>\n<\/div>\n<p>И так, теперь у нас есть набор необходимых сертификатов для работы с Push сообщениями на iOS.<\/p>\n<h2>Google и GCM<\/h2>\n<p>Для работы с Google и GCM мы будем использовать библиотеку <a href=\"https:\/\/github.com\/CodeMonkeysRu\/GCMMessage\">GCM PHP Server Library<\/a>. Скачанный архив библиотек и пример работы из коробки у меня по какой-то причине отказался работать, поэтому пришлось немного модифицировать код.<\/p>\n<p>Для работы с GCM нам потребуется API ключ проекта. Выполняем следующие действия:<\/p>\n<ol start=\"1\">\n<li>Открываем <a href=\"https:\/\/console.developers.google.com\/project\">консоль разработчика Google<\/a>.<\/li>\n<li>Выбираем интересующий нас проект.<\/li>\n<li>Открываем раздел <b>«APIs & auth»<\/b> — <b>«Credentials»<\/b> и копируем ключ Server Key.<\/li>\n<li>Если вы ещё не создавали ключи, то вам потребуется включить API «Google Cloud Messaging for Android».<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/apikey.png\" width=\"1280\" height=\"864\" alt=\"API ключ.\" \/>\n<\/div>\n<p>Теперь у нас имеются все необходимые данные для организации PHP сервера рассылки Push сообщений.<\/p>\n<h2>База данных<\/h2>\n<p>Для рассылки Push сообщений на устройства пользователей используются токены устройств, которые выдаётся серверами Google и Apple, т. е. для получения Push сообщения, токен устройства должен быть зарегистрирован в системе. Наш сервер так же отправки Push сообщений будет использовать токены устройств. Для хранения токено устройств, ID устройств и платформы я использовал базу данных.<\/p>\n<p>Текст скрипта для создания базы данных выглядит так.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE TABLE devices (\n  id int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Уникальный идентификатор  записи в таблице',\n  deviceID varchar(255) NOT NULL COMMENT 'Идентификатор устройства',\n  deviceToken varchar(255) NOT NULL COMMENT 'Токен устройства',\n  devicePlatform varchar(255) NOT NULL COMMENT 'Платформа устройства',\n  PRIMARY KEY (id),\n  UNIQUE INDEX deviceID (deviceID)\n)\nENGINE = MYISAM\nAUTO_INCREMENT = 20\nAVG_ROW_LENGTH = 166\nCHARACTER SET utf8\nCOLLATE utf8_general_ci\nCOMMENT = 'Зарегистрированные устройства для рассылки PUSH сообщений';<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/db-table.png\" width=\"263\" height=\"179\" alt=\"Таблица для хранения токенов.\" \/>\n<\/div>\n<p>Для добавления устройств в базу данных используется отдельная функция скрипта сервера, но об этом чуть позже.<\/p>\n<h2>Сервер<\/h2>\n<p>Переходим к самому серверу и его настройке. Все файлы я выложу отдельным архивом.<br \/>\nСуть скрипта состоит в следующем: подключаем библиотеки для работы с Push, настраиваем сертификаты и API ключ и с помощью имеющихся функций выполняем необходимые действия, будь то рассылка сообщений, регистрация устройств и пр.<\/p>\n<p>В состав сервера входит файл конфигурации. Приведу отдельно его текст.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;?php\n\n# Переменные для работы  с базой данных\n$config['db']['host'] = &quot;localhost&quot;;\n$config['db']['name'] = &quot;Имя БД&quot;;\n$config['db']['user'] = &quot;Пользователь БД&quot;;\n$config['db']['pass'] = &quot;Пароль БД&quot;;\n\n# Управление рассылкой. True - рассылка производится, false - рассылка отключена.\n$config['apn']['send'] = true;\n$config['gcm']['send'] = true;\n\n# Ключи для доступа к сервисам\n# Ключ для доступа Google Server API\n$config['gcm']['apikey'] = &quot;ВАШ API КЛЮЧ&quot;;\n# Путь к сертификатам APN для подключения к серверу рассылки\n$config['apn']['sert'] = 'Certificates\/server_certificates_bundle_sandbox.pem';\n$config['apn']['sert_prod'] = 'Certificates\/server_certificates_bundle_prod.pem';\n$config['apn']['RootCertificat'] = 'Certificates\/entrust_root_certification_authority_2048.pem';\n$config['apn']['production'] = false;\n\n?&gt;<\/code><\/pre><p>Думаю, что раздел конфигурации базы данных не требует объяснения, тут надо указать настройки для доступа к базе данных, в которой хранится таблица <b>«Devices»<\/b>.<\/p>\n<p>Параметры:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$config['apn']['send'] = true;\n$config['gcm']['send'] = true;<\/code><\/pre><p>Отвечают за включение или отключение рассылки Push сообщений, если значение false, то рассылка на указанную платформу не производится.<\/p>\n<p>Дальше идут настройки API ключа и указание каталогов сертификатов, что в общем-то тоже я думаю понятно всем.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Ключи для доступа к сервисам\n# Ключ для доступа Google Server API\n$config['gcm']['apikey'] = &quot;ВАШ API КЛЮЧ&quot;;\n# Путь к сертификатам APN для подключения к серверу рассылки\n$config['apn']['sert'] = 'Certificates\/server_certificates_bundle_sandbox.pem';\n$config['apn']['sert_prod'] = 'Certificates\/server_certificates_bundle_prod.pem';\n$config['apn']['RootCertificat'] = 'Certificates\/entrust_root_certification_authority_2048.pem';<\/code><\/pre><p>Отдельно рассмотрим ключ:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$config['apn']['production'] = false;<\/code><\/pre><p>Данный ключ переключает режим работы сервера. Development или Production режимы рассылки.<\/p>\n<p>Как можно заметить, все сертификаты необходимо положить в каталог «Certificates» рядом со скрипом.<\/p>\n<p>Если при генерации сертификатов Apn использовался пароль, то в настройках, необходимо указать пароль:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$config['apn']['sertPass'] = 'пароль сертификата';<\/code><\/pre><h2>Работа со скриптом<\/h2>\n<p>После заполнения файла конфигурации скрипт готов к работе, осталось зарегистрировать устройства.<br \/>\nСкрипт сервера push.php принимает 2 значения параметра <b>action<\/b>:<\/p>\n<ul>\n<li><b>register-device<\/b><\/li>\n<li><b>send-push<\/b><\/li>\n<\/ul>\n<p>В каждом действии требуются дополнительные параметры. Для регистрации устройства дополнительными параметрами являются:<\/p>\n<ul>\n<li><b>did<\/b> — Идентификатор устройства (не используется, но на всякий случай).<\/li>\n<li><b>token<\/b> — токен устройства, используется для рассылки Push сообщений.<\/li>\n<li><b>platform<\/b> — платформа устройства, используется функциями рассылки. Может принимать 2 значения: <b>ios<\/b> или <b>andoid<\/b>.<\/li>\n<\/ul>\n<p>Для рассылки Push сообщений используется действие send-push и принимается всего 1 дополнительный параметр: <b>text<\/b> — текст Push сообщения.<\/p>\n<p>Примеры запросов:<\/p>\n<p>Регистрация устройства iOS<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">http:\/\/example.ru\/push.php?action=register-device&amp;did=DC92EFED-9271&amp;token=feaab9d122f53a4fdca&amp;platform=ios<\/code><\/pre><p>Регистрация устройства Android<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">http:\/\/example.ru\/push.php?action=register-device&amp;did=DC92EFED-9271&amp;token=feaab9d122f53a4fdca&amp;platform=andoid<\/code><\/pre><p>Отправка Push сообщений<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">http:\/\/example.ru\/push.php?action=send-push&amp;text=Добрый день, мой господин!<\/code><\/pre><p>Первые два запроса регистрируют устройства в базе данных и в момент рассылки скрипты выбирает токены устройств по полю platform и производит отправку Push сообщений.<\/p>\n<p>Второй запрос производит рассылку Push сообщения все зарегистрированным устройствам.<\/p>\n<p>В общем-то, всё достаточно просто, каждый желающий может в дальнейшем модифицировать скрипт по своему желанию, вводя защиту от несанкционированного доступа и пр. Прошу меня не пинать, за полное отсутствие защиты в скрипте, скрипт призван показать логику и рабочий пример работы с Push сообщениями. Плюс данного скрипта состоят в том, что данные мы можем отправлять с любой платформы, будь то веб форма, Windiws приложения или мобильные приложения.<\/p>\n<h2>Delphi<\/h2>\n<p>Настало время рассмотреть небольшой код написанный для Delphi, который позволяет регистрировать токены устройств на нашем сервере. Каждое мобильное устройство после запуска приложения получает свой DeviceID и токен, после чего отправляет полученные данные на наш сервер.<\/p>\n<p>В разделе public нашего юнита добавляем следующие строки:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">public\n    { Public declarations }\n    APushService : TPushService;\n    AServiceConnection : TPushServiceConnection;<\/code><\/pre><p>А в раздел type добавляем описание 2-х функций:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">procedure OnReceiveNotificationEvent(Sender: TObject; const ANotification : TPushServiceNotification);\n    procedure OnServiceConnectionChange(Sender: TObject; AChange : TPushService.TChanges);<\/code><\/pre><p>В момент отображения формы добавляем код получения DID и токена. Будьте внимательны, значение <b>PROJECTNUM<\/b> необходимо заменить на свой номер проекта из личного кабинета Google разработчика.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/\/ На данном этапе происходит регистрация устройства для получения Push.\nprocedure TMainForm.FormShow(Sender: TObject);\nvar\n  ADeviceID, ADeviceToken : string;\nbegin\n\n  \/\/ Получение и отправка токена устройства\n  {$ifdef ANDROID}\n    \/\/ Для Android\n    APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);\n    APushService.AppProps[ TPushService.TAppPropNames.GCMAppID ] := 'PROJECTNUM';\n  {$else}\n    \/\/ Для iOS\n    APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.APS);\n  {$endif}\n  \/\/ Создаём подключение к серверу\n  AServiceConnection := TPushServiceConnection.Create( APushService );\n  \/\/ Активируем подключение\n  AServiceConnection.Active   := True;\n  \/\/ Подключаем делегаты\n  AServiceConnection.OnChange := OnServiceConnectionChange;\n  AServiceConnection.OnReceiveNotification := OnReceiveNotificationEvent;\n\n  ADeviceID    := APushService.DeviceIDValue[ TPushService.TDeviceIDNames.DeviceID ];\n  ADeviceToken := APushService.DeviceTokenValue[ TPushService.TDeviceTokenNames.DeviceToken ];\n\n  if (ADeviceID &lt;&gt; '') AND (ADeviceToken &lt;&gt; '') then\n  begin\n\n    \/\/ Регистрируем устройство на сервере для отправки push сообщений\n    RegisterDevice(ADeviceID, ADeviceToken);\n\n  end;\n\nend;<\/code><\/pre><p>Так же, надо добавить функцию, которая срабатывает при изменении состояния получения DID и токена.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/\/ Устройства не всегда успевают получить токен,\n\/\/\/ поэтому при изменении состояния опять проверяем токен\nprocedure TMainForm.OnServiceConnectionChange(Sender: TObject;\n  AChange : TPushService.TChanges);\nvar\n  ADeviceID, ADeviceToken : string;\nbegin\n    \/\/ При измении состояния компонента\n    ADeviceID    := APushService.DeviceIDValue[ TPushService.TDeviceIDNames.DeviceID ];\n    ADeviceToken := APushService.DeviceTokenValue[ TPushService.TDeviceTokenNames.DeviceToken ];\n\n    if (ADeviceID &lt;&gt; '') AND (ADeviceToken &lt;&gt; '') then\n    begin\n\n      \/\/ Регистрируем устройство на сервере для отправки push сообщений\n      RegisterDevice(ADeviceID, ADeviceToken);\n\n    end;\nend;<\/code><\/pre><p>Для вывода Push сообщения добавляем функцию:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/\/ Процедура вывода сообщение при получении Push уведомления от сервера\nprocedure TMainForm.OnReceiveNotificationEvent(Sender: TObject;\n  const ANotification : TPushServiceNotification);\nvar\n  MessageText : string;\nbegin\n  \/\/ Получаем текст сообщения в зависимости ль платформы\n  {$ifdef ANDROID}\n    MessageText := ANotification.DataObject.GetValue('message').Value;\n  {$else}\n    MessageText := ANotification.DataObject.GetValue('alert').Value;\n  {$endif};\n\n  \/\/ Выводим сообщение\n  ShowNotification(MessageText, 0);\nend;<\/code><\/pre><p>В результате мы получаем почти готовую программу. Кто был более внимательным, заметил, что в коде есть несколько функций, не объявленных ранее, таких как <b>ShowNotification<\/b> или <b>RegisterDevice<\/b>. Для удобства, я вынес их в отдельный файл global.pas. Достаточно добавить данный файл в проект, чтобы не копипастить функции. В данном файле вам потребуется заменить константу DOMAIN для указания пути к файлу скрипта на сервере, и если вы положили скрипт не в корне сервера, а в случайный каталог, то потребуется внести дополнительные изменения для указания точной адресации.<\/p>\n<p>Так же имеется функция <b>SendPush<\/b>, которая позволяет отправлять Push сообщения прямо с устройства.<\/p>\n<p>Все функции в файле global.pas имеют подробное описание и думаю их использование не вызовет никаких вопросов.<\/p>\n<p>Таким образом мы получаем устройства, которые регистрируются в системе, отправляя свои DID и токены скрипту, а скрипт записывает их в базу данных для дальнейшего использования при отправке Push сообщений. Если в базе имеются токены устройств, на которых программа не установлен (удалена), то такие токены будут удалены из базы данных после попытки отправки Push сообщений.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/db.png\" width=\"751\" height=\"128\" alt=\"Зарегистрированные устройства.\" \/>\n<\/div>\n<h2>Используемые файлы.<\/h2>\n<p><a href=\"http:\/\/alexbirukov.ru\/files\/push-server\/global.pas\">Файл global.pas<\/a><br \/>\n<a href=\"http:\/\/alexbirukov.ru\/files\/push-server\/Push_Server.7z\">PHP сервер Push сообщений<\/a><\/p>\n<h2>Заключение<\/h2>\n<p>В данной статье я попытался максимально подробно изложить принципы и алгоритмы работы с Push сообщениями с использованием дополнительных библиотек GCMMessage и ApnsPHP в php скрипте и взаимодействие с программным обеспечением (в моём случае Windows приложения и мобильные платформы).<\/p>\n<p>Данная статья не претендует на оригинальность и истину последней инстанции. Имеются открытые места в безопасности, такие, как сертификаты без паролей, открытый доступ к функциям скрипта без идентификации пользователей и пр.<\/p>\n<p>Если у кого-нибудь будет желание доработать данный скрипт в плане безопасности или внести поправки я буду только рад. Ваши изменения и замечания вы можете писать в комментариях к статье.<\/p>\n<p><b>UPDATE<\/b><\/p>\n<p>Для удобства, загрузил проект на <a href=\"https:\/\/github.com\/alexbirukov\/PHP-Push-Sender\">GitHub<\/a>.<\/p>\n<p><b>UPDATE 2<\/b> из комментария читателя<\/p>\n<blockquote>\n<p>Если у кого не работает на Rad Studio 10.2, то вместо «AServiceConnection.Active := True;» сделайте так:<\/p>\n<\/blockquote>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/ Активируем подключение\nTTask.Run(\nprocedure\nbegin\nAServiceConnection.Active := True;\nend\n);<\/code><\/pre><p>В uses должно быть System.Threading.<\/p>\n",
            "date_published": "2015-10-02T14:13:19+05:00",
            "date_modified": "2018-12-23T22:27:53+05:00",
            "tags": [
                "Android",
                "ApnsPHP",
                "Delphi",
                "GCMMessage",
                "iOS",
                "PHP",
                "Push",
                "кроссплатформенность",
                "программирование",
                "сервер"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/keychain.png",
            "_date_published_rfc2822": "Fri, 02 Oct 2015 14:13:19 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "326",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "jquery\/jquery.js",
                    "fotorama\/fotorama.css",
                    "fotorama\/fotorama.js",
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/keychain.png",
                    "https:\/\/alexbirukov.ru\/pictures\/keychain-2.png",
                    "https:\/\/alexbirukov.ru\/pictures\/keychain3.png",
                    "https:\/\/alexbirukov.ru\/pictures\/keychain4.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert2.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert4.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert5.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert3.png",
                    "https:\/\/alexbirukov.ru\/pictures\/apikey.png",
                    "https:\/\/alexbirukov.ru\/pictures\/db-table.png",
                    "https:\/\/alexbirukov.ru\/pictures\/db.png"
                ]
            }
        }
    ],
    "_e2_version": 4134,
    "_e2_ua_string": "Aegea 11.3 (v4134)"
}