Отправка Push-уведомлений через сервис Firebase Cloud Messaging по протоколу FCM HTTP v1 API

Публикация № 1408766

Разработка - Практика программирования

push push-уведомления firebase fcm fcm-push firebase-push

При разработке нативного приложения Android для ТСД, в котором присутствует функционал отображения задач кладовщикам, созданных в 1С, возникла необходимость отправлять push-уведомления о появлении новых задач. Для отправки таких уведомлений было решено использовать сервис Firebase Cloud Messaging (FCM). Так как для 1С, в отличии от других языков программирования, не существует готовых библиотек, что вполне логично, то очевидным способом отправки является использование протокола HTTP. Однако, существующая информация в интернете в части 1С содержит только сведений об отправке push-уведомлений через этот сервис с использованием устаревшего протокола HTTP Firebase Cloud Messaging. Сам Google не рекомендует использовать данный протокол и настоятельно склоняет к переходу на новый протокол FCM HTTP v1 API. Что ж, пришлось разбираться самостоятельно.

Авторизация для выполнения запросов к сервисам Google.

Основным отличием, помимо формата самого отправляемого сообщения, является способ авторизации. В отличии от постоянного ключа (Web API Key, который, нужно заметить, для новых проектов вообще не доступен), который передаётся в заголовке при использовании старого протокола, теперь необходимо отправлять ключ доступа (access token), срок действия которого максимально может составлять один час. По истечению срока действия необходимо получать новый ключ доступа для доступа к сервисам Google. Сделано это для увеличения безопасности. Если такой ключ доступа попадёт в посторонние руки, то максимум через час он уже будет недействителен.

Так же в качестве плюсов нового протокола приводится более эффективная настройка сообщений для разных платформ. Можно указать общие параметры уведомления и настроить дополнительные определения для конкретных платформ (Android, APNS, Web push protocol).

И если отправка самого push-уведомления через сервис FCM не вызывает сложностей (достаточно сформировать JSON объект согласно описанию https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages?hl=ru и отправить его в POST запросе по адресу https://fcm.googleapis.com/v1/projects/{идентификатор-проекта}/messages:send, указав в заголовке ключ доступа, речь о котором идёт выше), то вот как получать этот ключ пришлось разбираться более детально.

Можно, конечно, получать ключ с использованием авторизации пользователя через OAuth2. Это когда открывается форма c веб-страницей, в которой выполняется переход на сайт Google для авторизации, а после входа в свою учётную запись возвращается ключ доступа. Потом периодически по истечению срока действия ключа выполняется HTTP запрос для обновления этого ключа уже без участия пользователя. Такой метод использовался мной для обращения к сервисам Google Карты и Календарь. Но в данной ситуации захотелось выполнять авторизацию (получать ключ доступа) от имени сервисного аккаунта, т. е. вообще без участия пользователя.

Для выполнения такой авторизации используется JSON Web Token, который подписывается приватным ключом и отправляется на сервер авторизации. В ответ приходит ключ доступа. Когда срок действия этого ключа истекает, необходимо повторить процесс авторизация для получения нового ключа.

Подробно можно ознакомиться здесь: https://developers.google.com/identity/protocols/oauth2/service-account#httprest

Далее мы рассмотрим вкратце, как это сделать на 1С и по-русски)).

Получение приватного ключа для выполнения авторизации.

В первую очередь, нам понадобится приватный ключ, который можно скачать в настройках проекта Firebase. Как создавать такой проект мы рассматривать не будем, информации на эту тему достаточно в интернете, в том числе и на этом сайте. А если вы ранее использовали сервисы Firebase (например, для отправки push-уведомлений по устаревшему протоколу), то такой проект у вас уже есть.

Переходим к настройкам своего проекта Firebase на закладку Service Accounts и нажимаем кнопку Generate new private key. Браузером будет скачан JSON файл с данными приватного ключа. Внимание! Храните этот файл в надёжном хранилище и не допускайте его утечки.

Далее необходимо сгенерировать JSON Web Token (JWT) и подписать его приватным ключом для отправки на сервер авторизации.

Чтение приватного ключа в 1С.

Приватный ключ является объектом JSON. Ниже приведён пример содержимого ключа.

{
  "type": "service_account",
  "project_id": "fir-push-for-1c",
  "private_key_id": "355...b06",
  "private_key": "-----BEGIN PRIVATE KEY-----\n[СОДЕРЖИМОЕ ПРИВАТНОГО КЛЮЧА]\n-----END PRIVATE KEY-----\n",
  "client_email": "firebase-...@fir-push-for-1c.iam.gserviceaccount.com",
  "client_id": "106...782",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-hmjr4%40fir-push-for-1c.iam.gserviceaccount.com"
}

Этот ключ понадобится для создания подписанного JWT, поэтому необходимо его прочитать из файла и преобразовать в Структуру.

ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл("{путь_к_файлу_секретного_ключа}");

СекретныйКлюч = ПрочитатьJSON(ЧтениеJSON);

ЧтениеJSON.Закрыть();

Создание JWT.

JWT является строкой и состоит из трёх частей, разделённых точкой: заголовок, данные авторизации (тело), цифровая подпись. Каждая часть представляет собой строку Base64.

{Заголовок Base64}.{Тело Base64}.{Подпись Base64}

Для получения подписи необходимо подписать приватным ключом первые две части JWT.

{Заголовок Base64}.{Тело Base64}

И добавить полученное значение подписи в конец JWT через точку.

Формат заголовка JWT.

Формат заголовка представляет собой JSON объект, содержащий два параметра:

  • alg – тип алгоритма, по которому формируется подпись. Всегда используется алгоритм RSA SHA-256, поэтому значение этого параметра RS256.
  • typ – тип формата. Всегда JWT token, поэтому значение этого параметра JWT.

Таким образом заголовок будет всегда одним и тем же:

{"alg": "RS256", "typ": "JWT"}

В 1С можно просто устанавливать эту строку. Для преобразования простой строки в Base64 можно создать соответствующую процедуру.

Функция СтрокаВСтрокуBase64(ИсходнаяСтрока)
	
	Поток = Новый ПотокВПамяти;
	
	ЗаписьТекста = Новый ЗаписьТекста(Поток, КодировкаТекста.UTF8);
	ЗаписьТекста.Записать(ИсходнаяСтрока);
	ЗаписьТекста.Закрыть();
	
	ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
	Результат = Base64Строка(ДвоичныеДанные);
	
	// Необходимо так же удалить разделители ВК + ПС
	Результат = СтрЗаменить(Результат, Символы.ВК + Символы.ПС, "");
	
	Возврат Результат;
	
КонецФункции

В результате код получения заголовка JWT будет выглядеть следующим образом.

ЗаголовокJWT = СтрокаВСтрокуBase64("{""alg"":""RS256"", ""typ"":""JWT""}");

Формат данных авторизации (тело JWT).

Тело JWT так же является объектов JSON и содержит следующие параметры:

  • iss – адрес электронной почты сервисного аккаунта проекта Firebase.
  • scope – разрешения, которые необходимы. Для возможности отправлять push-уведомление необходимо разрешение https://www.googleapis.com/auth/firebase.messaging. Со всем значениями можно ознакомиться по адресу https://developers.google.com/identity/protocols/oauth2/scopes.
  • aud – всегда имеет значение https://oauth2.googleapis.com/token.
  • iat – дата, начиная с которой будет действовать полученный ключ доступа. Значение содержит количество секунд, прошедших с 1 января 1970 года.
  • exp – дата окончания действия ключа доступа. Значение содержит количество секунд, прошедших с 1 января 1970 года. Значение не может быть больше даты начала срока действия ключа чем на час (3600 секунд).

Сформировать тело JWT в 1С можно следующим образом.

// Вычисляем количество секунд с 01.01.1970 00:00:00
ДатаВыдачи = ТекущаяУниверсальнаяДата() - '19700101';
// Максимальный срок действия - 1 час (3600 секунд).
ДатаОкончания = ДатаВыдачи + 3600;

// Простой объект JSON сформируем сразу как строку.
ШаблонТела =
"{
|	""iss"": ""%1"",
|	""scope"": ""%2"",
|	""aud"": ""%3"",
|	""exp"": %4,
|	""iat"": %5
|}";
// Необходимые данные подставим из считанного ранее из файла приватного ключа.
Тело = СтрШаблон(ШаблонТела,
	СекретныйКлюч.client_email,
	"https://www.googleapis.com/auth/firebase.messaging",
	СекретныйКлюч.token_uri,
	Формат(ДатаОкончания, "ЧГ="),
	Формат(ДатаВыдачи, "ЧГ="));
	
ТелоJWT = СтрокаВСтрокуBase64(Тело); // Конечный результат должен быть строкой Base64.

Формирование подписи JWT.

После получения строк Base64 заголовка и тела их необходимо соединить через точку и вычислить цифровую подпись полученной строки с использование приватного ключа, содержащемся в скачанном выше файле. К сожалению, встроенные средства криптографии 1С не позволяет это сделать, поэтому для формирования подписи используется внешняя программа OpenSSL.
Для формирования подписи этой программой необходимо выполнить следующую команду системы:

openssl.exe dgst -sha256 -sign <имя_приватного_ключа> -out <имя_файла_подписи> <имя_подписанного_файла>

Таким образом для получения подписи нам необходимо сохранить в файлы на диске полученную строку для подписи и приватный ключ, выполнить указанную выше команду, подставив нужные имена файлов, после чего считать подпись из созданного файла <имя_файла_подписи>.

Создадим вспомогательную процедуру для записи строки в файл на диске. Это должны быть текстовые файлы в формате UTF-8.

Процедура ЗаписатьСтрокуВФайл(Строка, ИмяФайла)
	
	// Используется поток, чтобы записать текст в формате UTF-8 без BOM.
	Поток = Новый ПотокВПамяти;
	
	ЗаписьТекста = Новый ЗаписьТекста(Поток, КодировкаТекста.UTF8, , , Ложь);
	ЗаписьТекста.Записать(Строка);
	ЗаписьТекста.Закрыть();
	
	ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
	ДвоичныеДанные.Записать(ИмяФайла);
	
КонецПроцедуры

Далее реализуем алгоритм по формированию подписи с использованием OpenSSL.

// Создадим временный каталог для хранения файлов.
КаталогФайлов = ПолучитьИмяВременногоФайла();
СоздатьКаталог(КаталогФайлов);

// Зададим имена файлов.
ИмяФайлаКлюча = КаталогФайлов + "\private.key";
ИмяФайлаJWT = КаталогФайлов + "\jwt.txt";
ИмяФайлаПодписи = КаталогФайлов + "\jwt.sgn";

// Запишем подписываемые данные и приватный ключ в файлы.
ДанныеДляПодписи = ЗаголовокJWT + "." + ТелоJWT;
ЗаписатьСтрокуВФайл(ДанныеДляПодписи, ИмяФайлаJWT);
ЗаписатьСтрокуВФайл(СекретныйКлюч.private_key, ИмяФайлаКлюча);

// Сфомируем команду для формирования подписи.
OpenSsl = "<Путь_к_OpenSLL>\bin\openssl.exe";
СтрокаКоманды = OpenSsl + " dgst -sha256 -sign " + ИмяФайлаКлюча + " -out " + ИмяФайлаПодписи + " " + ИмяФайлаJWT;
КодВозврата = Неопределено;

// Выполним команду для формирования подписи.
ЗапуститьПриложение(СтрокаКоманды, , Истина, КодВозврата);

Если КодВозврата <> 0 Тогда
	// Что-то пошло не так.
	УдалитьФайлы(КаталогФайлов);
	ВызватьИсключение СтрШаблон(
		НСтр("ru='Произошла ошибка при подписании JSON Web Token. Код возврата: %1'"),
		КодВозврата);
КонецЕсли; 

// Прочитаем полученную подпись из файла, как двоичные данные.
ДанныеПодписи = Новый ДвоичныеДанные(ИмяФайлаПодписи);

// Преобразуем подпись в строку Base64...
ПодписьJWT = Base64Строка(ДанныеПодписи);
// ... и удалим разделители ВК + ПС
ПодписьJWT = СтрЗаменить(ПодписьJWT, Символы.ВК + Символы.ПС, "");

// Удалим временный каталог с файлами.
УдалитьФайлы(КаталогФайлов);

После того, как получена подпись, можем сформировать итоговый JSON Web Token.

JWT = ЗаголовокJWT + "." + ТелоJWT + "." + ПодписьJWT;

Авторизация и получение ключа доступа с использованием сформированного JWT.

Теперь мы можем выполнить авторизацию и получить ключ доступа для обращения к сервисам Google.

Для этого необходимо выполнить HTTP POST запрос по адресу https://oauth2.googleapis.com/token.

В теле запроса необходимо передать объект JSON, содержащий два параметра:

  • grant_type – всегда содержит значение urn:ietf:params:oauth:grant-type:jwt-bearer.
  • assertion – сформированный выше подписанный JSON Web Token.

Такой запрос будет выглядеть следующим образом.

// В заголовках установим тип содержимого тела - JSON.
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json");

// Простой объект JSON сформируем сразу как строку.
ШаблонЗапроса = 
"{
|	""grant_type"": ""%1"",
|	""assertion"": ""%2""
|}";
ПараметрыЗапроса = СтрШаблон(ШаблонЗапроса,
	"urn:ietf:params:oauth:grant-type:jwt-bearer",
	JWT
);

// Создадим HTTP запрос с нужными параметрами.
Запрос = Новый HTTPЗапрос("token", Заголовки);
Запрос.УстановитьТелоИзСтроки(ПараметрыЗапроса);

// Создадим защищенное HTTPS соединение.
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL;
Соединение = Новый HTTPСоединение("oauth2.googleapis.com", , , , , , ЗащищенноеСоединение);

// И отправим запрос с методом POST на сервер.
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

В ответе придёт JSON объект, содержащий ключ доступа (access_token) и срок действия (дата, после которой ключ станет недействительным).

Произведём чтение этих данных из ответа.

ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();

ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоОтвета);

СтруктураОтвета = ПрочитатьJSON(ЧтениеJSON);
	
ЧтениеJSON.Закрыть();

Если Ответ.КодСостояния <> 200 Тогда
	ВызватьИсключение СтруктураОтвета.error_description;
КонецЕсли; 

КлючДоступа = СтруктураОтвета.access_token;
// Определим срок действия ключа, после которого он устареет и необходимо будет
// вновь выполнить авторизацию.
СрокДействия = ТекущаяУниверсальнаяДата() + СтруктураОтвета.expires_in;

// Можно сохранить ключ доступа чтобы не производить авторизацию при каждой отправке сообщения.
// Если в вашей конфигурации используется БСП, то это можно сделать, например, так.
ДанныеКлючаДоступа = Новый Структура("КлючДоступа, СрокДействия", КлючДоступа, СрокДействия);
УстановитьПривилегированныйРежим(Истина);
ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище("GoogleAPI", ДанныеКлючаДоступа);
УстановитьПривилегированныйРежим(Ложь);

Теперь, имея действующий ключ доступа мы может выполнять запросы к сервисам Google, в том числе и для отправки push-уведомлений.

Отправка push-уведомлений.

Как было сказано вначале, для отправки push-уведомлений необходимо сформировать JSON-объект, заполненный необходимыми данными и отправить его по адресу https://fcm.googleapis.com/v1/projects/{идентификатор-проекта}/messages:send, указав в заголовке ключ доступа.

Для этой статьи мной был создан проект Firebase с идентификатором «fir-push-for-1c» (Project ID на закладке General настроек проекта). Поэтому адрес, по которому необходимо отправить push-уведомление будет выглядеть следующим образом: https://fcm.googleapis.com/v1/projects/fir-push-for-1c/messages:send.

Объект JSON называется message и содержит следующий поля:

  • data – произвольные передаваемые данные, которые будут обработаны приложением, получившим push-уведомление. В терминах 1С – это Соответствие, где ключ и значение имеют тип «Строка».
  • notification – объект (в терминах 1С – Структура), описывающий само уведомление (заголовок, текст сообщения и изображение).
  • android – объект, содержащий специфичные параметры для Android устройств (приоритет, цвет сообщение, звук, видимость и прочие параметры).
  • webpush – объект, содержащий параметры протокола Webpush.
  • apns – объект, содержащий специальные параметры службы push-уведомлений Apple.
  • token – идентификатор (токен) получателя. Данный идентификатор должен быть получен от устройства, на которое требуется отправлять уведомления. Получение идентификатора можно реализовать через http-сервис 1С. Например, при запуске мобильного приложения на устройстве Android, разработчик должен реализовать получение этого идентификатора и отправку его в базу 1С через http-сервис. Разработчик 1С должен сохранять этот идентификатор в БД и использовать его при отправке уведомлений на это устройство. Если вы реализовывали отправку уведомлений для приложений на мобильной платформе 1С, то вам должен быть знаком данный механизм (token в таком случае – ИдентификаторПодписчикаДоставляемыхУведомлений.ИдентификаторУстройства).

С подробным описанием этого объекта уведомлений можно ознакомиться по адресу https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages?hl=ru.

Напишем код, который отправит простое push-уведомление, содержащее заголовок, текст сообщения и данные о вымышленной задаче (тип задачи и её идентификатор). Заголовок и текст сообщения используются для отображения оповещения на экране устройства, а данные (data) используются непосредственно самим приложением, чтобы «знать» что, собственно говоря, пришло.

// Сформируем объект push-уведомления для отправки.
Уведомление = Новый Структура;
Уведомление.Вставить("token", "<Идентификатор_получателя>");

// Установим необходимые данные.
Уведомление.Вставить("data", Новый Соответствие);
Уведомление.data["task_id"] = "092309280";
Уведомление.data["task_type"] = "check_order";

// Зададим оповещение, отображаемое на экране.
Оповещение = Новый Структура;
Оповещение.Вставить("title", НСтр("ru='Создана новая задача'"));
Оповещение.Вставить("body", НСтр("ru='Проверить сборку ордера на отгрузку 123'"));

Уведомление.Вставить("notification", Оповещение);

// Для Android устройства можем указать дополнительные параметры оповещения,
// например, видимость уведомления.
КонфигурацияAndroid = Новый Структура;
КонфигурацияAndroid.Вставить("notification", Новый Структура("visibility", "PRIVATE"));

Уведомление.Вставить("android", КонфигурацияAndroid);

// Создадим итоговый объект уведомления.
PushСообщение = Новый Структура("message", Уведомление);

// И преобразуем его в JSON строку.
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();

ЗаписатьJSON(ЗаписьJSON, PushСообщение);

ТелоЗапроса = ЗаписьJSON.Закрыть();

// Отправим уведомление через FCM.

КлючДоступа = "<полученный_ранее_ключ_доступа>";

// Если ключ доступа был сохранён в безопасном хранилище, как было показано в коде выше,
// то можно воспользоваться следующим кодом.
УстановитьПривилегированныйРежим(Истина);
ДанныеКлючаДоступа = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища("GoogleAPI");
УстановитьПривилегированныйРежим(Ложь);

// Проверка сохраненного ключа доступа
КлючДоступаАктален = Тип(ДанныеКлючаДоступа) = Тип("Структура")
	И ТекущаяУниверсальнаяДата() < ДанныеКлючаДоступа.СрокДействия;
Если Не КлючДоступаАктален Тогда
	// Необходимо выполнить повторную авторизацию.
	// Как вариант, можно обновлять ключ доступа регламентным заданием по рассписанию.
	//....
КонецЕсли; 

КлючДоступа = ДанныеКлючаДоступа.КлючДоступа;

АдресРесурса = СтрШаблон("/v1/projects/%1/messages:send", "<Идентификатор_вашего_проекта_Firebase>");

Заголовки = Новый Соответствие;
// Заголовок авторизации с полученным ранее ключом доступа.
Заголовки.Вставить("Authorization", "Bearer " + КлючДоступа);
// Заголовок, указывающий тип содержимого тела запроса.
Заголовки.Вставить("Content-Type", "application/json");
	
Запрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса);

Соединение = Новый HTTPСоединение("fcm.googleapis.com", , , , , , Новый ЗащищенноеСоединениеOpenSSL);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Таким образом мы выполнили авторизацию, получили ключ доступа и отправили push-уведомление.

Библиотека отправки Push уведомления через Firebase Cloud Messaging.

"Для облегчения жизни" описанный выше код был собран в отдельные процедуры и функции для авторизации и отправки push-уведомлений в отдельную библиотеку, выполненную в виде расширения. Её можно подключить к своей конфигурации как расширение, либо добавить общие модули из этой библиотеки непосредственно в конфигурацию своего прикладного решения. Дополнительно необходимо будет реализовать получение идентификаторов получателей от мобильных устройств и загрузку приватного ключа из файла JSON.

Описание процедур и функций библиотеки.

Выполнение авторизации.

Для выполнения авторизации предназначен общий модуль fcm_АутентификацияGoogleAPIКлиентСервер, который содержит одну экспортную функцию ПолучитьКлючДоступаGoogleAPI.

Синтаксис:

ПолучитьКлючДоступаGoogleAPI(<СекретныйКлюч>, <Разрешения>, <ПутьКOpenSsl>, <СрокДействия>)

Параметры:

<СекретныйКлюч> (обязательный) - Строка - строка в формате JSON, содержащая данные секретного ключа. Как получать эту строку должен определять разработчик прикладного решения. Она может быть прочитана из файла на диске (например, можно поместить этот файл в папку, недоступной для чтение обычным пользователям, но доступной серверу 1С), получена из макета конфигурации (не самое удачное решение хранить таким образом конфиденциальные данные) или получена каким-либо другим образом.

Разрешения (обязательный) - Строка - требуемые разрешения от сервисов Google. Для отправки push-уведомлений необходимо указать значение https://www.googleapis.com/auth/firebase.messaging. Данное значение можно получить вызвав функцию библиотеки fcm_УведомленияКлиентСервер.РазрешениеFCMОтправкаУведомлений().

ПутьКOpenSSL (обязательный) - Строка - путь к программе OpenSSL для вычисления подписи JSON Web Token.

СрокДействия (необязательный) - Число - срок действия ключа доступа в секундах. Если не указан, то по умолчанию используется максимально возможное значение: 3600 секунд (1 час).

Возвращаемое значение:

Строка - ключ доступа (access token) к сервисам Google, полученный в результате авторизации.

Описание:

Выполняет авторизация на сервере Google и возвращает ключ доступа. В случае возникновения ошибки при авторизации будет вызвано Исключение.

Отправка push-уведомлений.

Для отправки push-уведомлений предназначен общий модуль fcm_УведомленияКлиентСервер. Данный модуль содержит функцию ОтправитьУведомление для отправки уведомлений и ряд служебный функций для формирования объектов уведомления.

ОтправитьУведомление

Синтаксис:

ОтправитьУведомление(<Уведомление>, <ПроектFirebase>, <КлючДоступа>)

Параметры:

Уведомление (обязательный) - Структура - структура, описывающая push-уведомление. Для формирование данной структуры можно использовать вспомогательные функции модуля fcm_УведомленияКлиентСервер (см. ниже).

ПроектFirebase (обязательный) - Строка - идентификатор проекта сервиса  Firebase.

КлючДоступа (обязательный) - Строка - ключ доступа к сервису Firebase Cloud Messaging.

Возвращаемое значение:

Строка - идентификатор Firebase Cloud Messaging отправленного уведомления.

Описание:

Выполняет отправку push-уведомления через Firebase Cloud Messaging. В случае возникновения ошибки при отправке уведомления будет вызвано Исключение.

Вспомогательные функции для создания структуры, описывающей push-уведомление.

СоздатьУведомление - возвращает структуру, описывающую push-уведомление и инициализированную пустыми значениями.

СоздатьОповещение - возвращает структуру, описывающую оповещение (Notification) и инициализированную пустыми значениями.

СоздатьКонфигурациюAndroid - возвращает структуру, описывающую конфигурацию push-уведомление для Android и инициализированную пустыми значениями.

СоздатьОповещениеAndroid - возвращает структуру, описывающую оповещение для Android (AndroidNotification) и инициализированную пустыми значениями.

СоздатьКонфигурациюWebPush - возвращает структуру, описывающую конфигурацию push-уведомление для Webpush protocol и инициализированную пустыми значениями.

СоздатьКонфигурациюAPNS - возвращает структуру, описывающую конфигурацию push-уведомление для Apple Push Notification Service и инициализированную пустыми значениями.

НастройкиСветовогоОповещения - возвращает структуру, описывающую настройки светового оповещения (LightSettings) и инициализированную пустыми значениями.

ЦветRGBA(R, G, B, A) - возвращает структуру, описывающую цвет RGBA:

  • R - Число - красный (red), дробное число от 0 до 1;
  • G - Число - зеленый (green), дробное число от 0 до 1;
  • B - Число - синий (blue), дробное число от 0 до 1;
  • A - Число - значение альфа-канала, определяющее прозрачность (alpha), дробное число от 0 до 1.

Ниже приведён пример отправки такого же push-уведомления, которое было приведено выше с использованием библиотеки.

// Сформируем объект push-уведомления для отправки.
Уведомление = fcm_УведомленияКлиентСервер.СоздатьУведомление();
Уведомление.token = "<Идентификатор_получателя>";

// Установим необходимые данные.
Уведомление.data["task_id"] = "092309280";
Уведомление.data["task_type"] = "check_order";

// Зададим оповещение, отображаемое на экране.
Оповещение = fcm_УведомленияКлиентСервер.СоздатьОповещение();
Оповещение.title = НСтр("ru='Создана новая задача'");
Оповещение.body = НСтр("ru='Проверить сборку ордера на отгрузку 123'");

Уведомление.notification = Оповещение;

// Для Android устройства можем указать дополнительные параметры оповещения,
// например, видимость уведомления.
ОповещениеAndroid = fcm_УведомленияКлиентСервер.СоздатьОповещениеAndroid();
ОповещениеAndroid.notification_priority = fcm_УведомленияКлиентСервер.ПриоритетОповещенияВысокий();
ОповещениеAndroid.visibility = fcm_УведомленияКлиентСервер.ВидимостьУведомленияПриватное();

КонфигурацияAndroid = fcm_УведомленияКлиентСервер.СоздатьКонфигурациюAndroid();
КонфигурацияAndroid.priority = fcm_УведомленияКлиентСервер.ПриоритетAndroidВысокий();
КонфигурацияAndroid.notification = ОповещениеAndroid;

Уведомление.android = КонфигурацияAndroid;

УстановитьПривилегированныйРежим(Истина);
ДанныеКлючаДоступа = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища("GoogleAPI");
УстановитьПривилегированныйРежим(Ложь);

// Проверка сохраненного ключа доступа
КлючДоступаАктален = Тип(ДанныеКлючаДоступа) = Тип("Структура")
	И ТекущаяУниверсальнаяДата() < ДанныеКлючаДоступа.СрокДействия;

Если Не КлючДоступаАктален Тогда
	// Ключ доступа не актуален. Необходимо выполнить авторизацию и сохранить новый ключ доступа.
		
	СрокДействия = 600; // 10 минут
	КлючДоступа = fcm_АутентификацияGoogleAPIКлиентСервер.ПолучитьКлючДоступаGoogleAPI(
		"<Передайте_загруженный_ключ_доступа>",
		fcm_УведомленияКлиентСервер.РазрешениеFCMОтправкаУведомлений(),
		СрокДействия
	);
	
	ДанныеКлючаДоступа = Новый Структура;
	ДанныеКлючаДоступа.Вставить("КлючДоступа", КлючДоступа);
	ДанныеКлючаДоступа.Вставить("СрокДействия", ТекущаяУниверсальнаяДата() + СрокДействия);
	
	УстановитьПривилегированныйРежим(Истина);
	ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище("GoogleAPI", ДанныеКлючаДоступа);
	УстановитьПривилегированныйРежим(Ложь);
	
Иначе
	
	КлючДоступа = ДанныеКлючаДоступа.КлючДоступа;
	
КонецЕсли; 

ИдентификаторУведомления = fcm_УведомленияКлиентСервер.ОтправитьУведомление(
	Уведомление, "<идентификатор_проекта_firebase>", КлючДоступа);

Сообщить(СтрШаблон(НСтр("ru='Уведомление отправлено. Идентификатор: %1'"), ИдентификаторУведомления));

Так же в состав библиотеки входит обработка, демонстрирующая отправку push-уведомлений.

Условия использования библиотеки отправки Push уведомления через Firebase Cloud Messaging.

Исходный код библиотеки отправки Push уведомления через Firebase Cloud Messaging распространяется под лицензий Apache 2.0. Вы можете свободно использовать, изменять и распространять его, в том числе и в коммерческих целях с обязательным указанием авторства. Подробнее см. текст лицензии http://www.apache.org/licenses/LICENSE-2.0

Исходный код также доступен на github: https://github.com/ltfriend/FCMPushFor1C

Работа была протестирована на версии 1С:Предприятия 8.3.18.1363.

Скачать файлы

Наименование Файл Версия Размер
Библиотека отправки Push уведомлений FCM (расширение)

.cfe 21,64Kb
3
.cfe 1.0.1.2 21,64Kb 3 Скачать

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Steelvan 96 24.03.21 12:14 Сейчас в теме
Как вариант, вместо родного мобильного приложения можно было обойтись родной 1С компонентой для вебгнезд и веб-мордой на html для мобильного обозревателя.
А вообще вариантов и технологий для решения подобных задач достаточно много, да.
2. rozer 282 30.03.21 17:03 Сейчас в теме
интересно а это Push и локальные уведомления еще актуально ? И 1С не переделала свой 1С:Центр уведомлений c GCM на FCM ?
3. Rootking2010 31.03.21 17:34 Сейчас в теме
Спасибо, очень своевременно сделали статью. Никак не получалось с авторизацией на FCM, пришлось переделать через pusher.com, а вот с Вашим расширением всё получилось и убрали не нужное звено.
Оставьте свое сообщение

См. также

Интеграция с бонусной программой лояльности ManyBonus

Управление взаимоотношениями с клиентами (СRM) Розничная торговля WEB v8 Розница УУ Абонемент ($m)

ManyBonus.com - бонусная программа лояльности на базе мессенджеров. Позволяет регистрировать клиента в программе лояльности через Telegram, Viber, VK, отправлять коды скидок в мессенджеры, получать уведомления при списании/начислении бонусных баллов, альтернатива сообщениям СМС.

3 стартмани

07.01.2021    2880    4    Anton64    0    

FormCodeGenerator Программная доработка форм. Часть 2 (Режим работы "Режим сравнения форм") на примере ERP 2.5

Практика программирования Адаптация типовых решений Прочие инструменты разработчика v8 1cv8.cf Абонемент ($m)

Данная публикация является продолжением описания функционирования обработки "FormCodeGenerator " в режиме сравнения форм и генерирования кода на основании сравнения. Подходит для перевода уже доработанных форм с интерактивной доработки на программную. Данный режим работы обработки снизит издержки при дальнейших обновлениях конфигураций.

5 стартмани

21.12.2020    4051    19    huxuxuya    11    

BIM: взаимодействие с платформой Autodesk Forge

WEB v8 1cv8.cf Строительство Абонемент ($m)

Предлагаемый пример демонстрирует широкие возможности для взаимодействия «1С:Предприятие» с платформой Autodesk Forge и позволяет вам получить базовые представления о применения технологий информационного моделирования в строительстве. Поддерживаются все версии платформы от 8.3.12 и выше до 8.3.18.

1 стартмани

25.11.2020    15572    6    kandr    2    

Работа с релизами 1С и договорами ИТС

WEB БСП (Библиотека стандартных подсистем) v8 1cv8.cf Абонемент ($m)

Работа с релизами 1С и партнерским кабинетом.

2 стартмани

15.08.2019    16773    52    RocKeR_13    35    

"Учет штрафов ГИБДД" с возможной загрузкой из открытых источников в интернет Расширение конфигурации 1С: Предприятие 8.3

Обработка документов WEB v8 v8::УФ 1cv8.cf Россия БУ УУ Абонемент ($m)

Расширение конфигурации Бухгалтерия предприятия, редакция 3.0 (при минимальных изменениях любой типовой конфигурации), позволяющее вести историю данных по штрафам ГИБДД для справочника транспортных средств компании. Бонусом поставляется внешняя обработка, способная загружать эти данные из открытых источников в интернет.

4 стартмани

30.12.2019    12212    18    capitan    11    

Односторонний файловый обмен с сайтом по ftp (1C 2 Web)

Обмен данными 1С Файловые протоколы обмена, FTP WEB v8 Розница УНФ ERP2 БП3.0 УТ11 КА2 ЗУП3.x Абонемент ($m)

Подходит под любую конфигурацию на управляемом интерфейсе на базе БСП 2.4.4 и выше. Позволяет гибко настроить выгрузку, практически любых, данных по расписанию на сервер ftp вашего ресурса. Ведение лога процесса выгрузки также предусмотрено.

3 стартмани

09.12.2019    6686    8    LamerSoft    0    

Вам нравятся запросы в 1С?

Практика программирования Разработка v8 v8::Запросы 1cv8.cf Абонемент ($m)

Речь не только о том, что простейший запрос с "легальным" оформлением растянется на пол-экрана, речь еще обо всем, что нужно написать "в нагрузку" к тексту запроса. Все эти "Новый Запрос", "УстановитьПараметр" и последующие пляски с обработкой результата... Пора с этим заканчивать!

1 стартмани

03.07.2019    23720    6    m-rv    90    

Проверка VAT номеров

WEB v8 1cv8.cf Абонемент ($m)

Обработка для вызова сервиса проверка VAT номера.

1 стартмани

26.11.2018    14932    3    wtlz    1    

Работа с публикациями "Инфостарт"

Практика программирования О сообществе WEB v8 УУ Абонемент ($m)

Работа с рублевыми публикациями на сайте "Инфостарт": ведение клиентов, заказов, обновление файлов публикации, рассылка обновлений.

1 стартмани

13.09.2018    24422    13    RocKeR_13    16    

Позиционирование в помещении с помощью нейросети по сигналу Wi-Fi. Интерактивная карта склада в 1С с показом позиции

Инструментарий разработчика Практика программирования v8 Абонемент ($m)

Данная публикация содержит в себе редактор и интерактивную карту склада или иного помещения, на которой в реальном времени отображается позиция устройства, координаты которого вычисляются по уровням сигнала нескольких роутеров Wi-Fi. В статье и приложенным к ней разработкам предлагаются инструменты и методика для реализации вычисления точной геопозиции внутри помещений с помощью нейронной сети. Конфигурация написана на релизе 1С:Предприятие 8.3.12.1412, клиентское приложение имеет минимальный уровень совместимости SDK -16.

5 стартмани

09.08.2018    31433    28    informa1555    26    

Работа с данными выбора

Практика программирования Работа с интерфейсом v8 Россия Абонемент ($m)

В управляемом интерфейсе заложена мощная возможность описывать связи реквизитов формы через параметры. Установка параметров связей позволяет ограничить выбор данных так, чтобы целостность данных была обеспечена на этапе ввода. Однако без дополнительного программирования задать можно только самые простые связи. Такие условия связи, как зависимость от реквизита через точку или зависимость через дополнительное отношение, заданное в регистре сведений - уже задать без программирования не получится.

1 стартмани

17.07.2018    56703    21    kalyaka    16    

Пример использования REST API Яндекс Диска

WEB v8 1cv8.cf Абонемент ($m)

Пример использования REST API Яндекс Диска: чтение диска, добавление каталога, загрузка файла, скачивание файлов или каталогов, удаление файлов или каталогов.

1 стартмани

26.06.2018    28994    46    MKFreeUser    15    

Обмен файловыми базами данных через Yandex диск

WEB v8 Россия Абонемент ($m)

Выполнение операций обмена с Yandex диском для файловых БД, по протоколу WebDav, в автоматическом или ручном режимах.

1 стартмани

11.06.2018    19069    7    slimper    1    

Конфигурация для просмотра публичных телеграм каналов

WEB v8 Абонемент ($m)

Просмотр и каталогизация в более удобном виде публичных телеграм каналов, групп и чатов.

1 стартмани

02.06.2018    19965    13    DO_WHILE_LOOP    7    

ВСТАВИТЬ В Справочник.Номенклатура (Код, Наименование) ЗНАЧЕНИЯ ("001", "Новый товар")

Практика программирования v8 v8::Запросы 1cv8.cf Абонемент ($m)

Вас не обманывают ваши глаза, это запрос на изменение данных! И это работает без прямого доступа к БД, регистрации и смс.

1 стартмани

01.06.2018    32941    88    m-rv    58    

Внешняя компонента для работы по Web-socket протоколу x32 x64

Разработка внешних компонент WEB v8 Абонемент ($m)

Кто когда-нибудь сталкивался с обменом данными по Web-Socket (wss) протоколу из 1С, тому известно, что в платформе отсутствуют данные механизмы (не путать с HTTP запросами и WebServices). Предлагается использовать внешнюю компоненту, написанную по технологии NativeAPI, для подключения и обмена с серверами из 1С-Предприятия, работающими по протоколу Web-Socket.

1 стартмани

30.03.2018    30416    38    Ditron    90    

Заполняем по шаблону (по умолчанию)

Практика программирования v8 v8::УФ 1cv8.cf Абонемент ($m)

Простой в подключении, универсальный и достаточно удобный механизм заполнения реквизитов произвольных документов/справочников значениями по умолчанию. Реализован в расширении, но может быть и непосредственно включен практически в любую конфигурацию на управляемых формах простым копированием одной формы и двух команд. Весь код в статье.

1 стартмани

08.02.2018    30954    20    mvxyz    17    

Сервер push сообщений “Push0k“ 18.05

WEB v8 1cv8.cf Абонемент ($m)

Аналог других “мессенджеров“. Позволяет практически все то же самое, что и другие решения. За исключением смайлов, эмодзи, голосовой и видео связи. Основное отличие от других решений, открыта и доступна для изменения серверная и клиентская часть месенджера. Общедоступной серверной части нет, за серверную часть отвечаете вы сами.

1 стартмани

19.12.2017    20462    12    PloAl    20    

Печатная форма, сделанная как расширение конфигурации для БП 3.0. Новые возможности БСП

Практика программирования Универсальные печатные формы v8 БП3.0 Абонемент ($m)

Печатные формы на внешних обработках скоро канут в лету. На смену им приходят ПФ, реализованные в виде расширений конфигурации. Не нашел на сайте примеров таких расширений. Привожу пример подобного расширения для БП 3.0.

1 стартмани

06.12.2017    29459    56    kwazi    6    

Подсистема Вики - интеграция 1С и сайта под управлением MediaWiki

WEB v8 Абонемент ($m)

Редактирование статей сайта Mediawiki из 1С. Формирование функционального описания конфигурации на сайте Вики.

1 стартмани

19.09.2017    31006    35    shmalevoz    20    

Работа с картой. Кадастровый учет (Росреестр). Тематические карты

WEB Рабочее место v8 v8::УФ 1cv8.cf Абонемент ($m)

Внешняя обработка для работы с картами в 1С. Получения изображения с публичной кадастровой карты России, построения тематических карт

1 стартмани

31.08.2017    21140    8    vipchep    0    

Расширения конфигураций 1С: учимся перехватывать методы

Практика программирования v8 v8::УФ 1cv8.cf Абонемент ($m)

В этой статье я на примерах разберу некоторые механизмы расширений конфигураций 1С. А именно «перехваты» методов модуля объекта и «перехваты» событий формы и элементов формы. Данная статья написана с учебными целями, чтобы показать, как при помощи расширений конфигурации можно делать такие доработки, ради которых раньше приходилось снимать конфигурацию с поддержки.

1 стартмани

30.05.2017    148000    13    signum2009    48    

Настройка рекламной кампании Яндекс.Директ на 30000 ключевых фраз за 60 минут - теперь это реально!

WEB v8 Реклама, PR и маркетинг Россия Абонемент ($m)

Конфигурация для настройки Яндекс.Директа.

10 стартмани

20.10.2016    31055    51    avalakh    10    

Конструктор-тестер http запросов в 1С

WEB Инструментарий разработчика v8 1cv8.cf Россия Абонемент ($m)

Данная обработка позволяет в несколько кликов конструировать http запросы на языке 1С и просматривать результаты их выполнения.

3 стартмани

19.08.2016    44958    307    hlopik    18    

1С: Предприятие + корпоративный чат, как наладить оперативные уведомления за 10 минут

Практика программирования v8 Абонемент ($m)

Как сделать автоматические уведомления о разных событиях из 1С в корпоративный чат MyChat для сотрудников компании

1 стартмани

14.08.2016    51012    36    Demanoidos    60    

Подсистема обмена данными с порталом ИМНС по электронным счетам-фактурам (автоматический обмен)

Внешние источники данных WEB Инструментарий разработчика v8 1cv8.cf Беларусь БУ НДС Абонемент ($m)

Подсистема включает документы и обработки для автоматического обмена данными с порталом ИМНС через web-сервис. Присутствует возможность заполнения данными типовых операций за период, учёта входящих документов, учёта произвольных исходящих документов. Приложены обработки для запуска задания планировщика на автоматический обмен данными.

1 стартмани

28.07.2016    35759    19    c1nil    4    

Хранение файлов в томах на диске (для УПП 1.3)

Практика программирования v8 УПП1 Абонемент ($m)

Доработка типовой УПП 1.3 в плане хранения присоединенных файлов вне базы данных

2 стартмани

05.06.2016    61964    11    wowik    32    

Остатки на каждый день в запросе

Практика программирования Учет ТМЦ Учет ТМЦ v8 1cv8.cf УУ Абонемент ($m)

Запрос формирует остатки товаров на каждый день в пределах выбранного периода.

1 стартмани

26.04.2016    67114    19    arakelyan    22    

Трекинг номеров РПО в Почте России

WEB Оптовая торговля Оптовая торговля v8 Оптовая торговля, дистрибуция, логистика Абонемент ($m)

Относительно недавно Почта России стандартизировала и описала сервисы получения информации о регистрируемом почтовом отправлении (РПО). Представляю вашему вниманию конфигурацию-обертку над сервисами Почты России. Она позволяет просто (http-запросы) и без изменений конфигурации подключить сервисы отслеживания к своим информационным системам.

2 стартмани

28.03.2016    29344    38    Smaylukk    3    

Выполнение JavaScript кода из 1С в объекте Поле HTML Документа (HTML 5) и вызов события в 1С ПриНажатии

Практика программирования v8 1cv8.cf Россия Абонемент ($m)

Пример выполнения JS кода из 1С в Поле HTML Документа под управляемыми формами, с удобным получением результата в 1С(С помощью вызова привязанного события ПриНажатии к элементу ПолеHTMLДокумента)

1 стартмани

22.03.2016    87771    165    igo1    54    

Количество дней недели (понедельников/вторников/...) в заданном диапазоне одним запросом

Практика программирования v8 Абонемент ($m)

При реализации периодического авто-заполнения маршрутных листов по графику (недельному) необходимо было просчитать стоимость всего периода, с условием выездов только по определенным дням. Заморачиваться с обходом результата не хотелось. Пришлось написать "Небольшой" запрос.

1 стартмани

03.03.2016    20272    1    Alexander.Shvets    5    

Простые радости жизни программиста 1С: выбор типа значения

Работа с интерфейсом Практика программирования v8 1cv8.cf Абонемент ($m)

Предлагаемая в работе обработка включает обычную и управляемую формы, которые максимально точно реализуют функциональность системного диалога выбора типа в толстом клиенте обычное приложение (включая оформление диалога). Эти формы имеют дополнительные интерфейсные удобства и могут быть использованы в качестве альтернативных диалогов выбора типа.

1 стартмани

17.02.2016    54117    54    yuraos    18    

Яндекс.Деньги "Благотворительность"

Инструментарий разработчика Практика программирования v8 1cv8.cf Абонемент ($m)

Яндекс.Деньги теперь в 1С. Форма для приема благотворительных взносов. Форму легко сделать и вставить на любую страницу сайта или блога. Платежи будут приходить на ваш кошелек. На форме есть три способа платежа: из кошелька, с банковской карты, с баланса мобильного.

1 стартмани

16.02.2016    25344    8    Tatitutu    5