Интеграция 1С-Битрикс с Firebase Cloud Messaging

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Интеграция 1С-Битрикс с Firebase Cloud Messaging
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Интеграция 1С-Битрикс с Firebase Cloud Messaging

Firebase Cloud Messaging (FCM) — инфраструктура Google для push-уведомлений на Android, iOS и в браузере. В отличие от OneSignal, FCM — это низкоуровневый транспорт без встроенного UI и сегментации. Интеграция с 1С-Битрикс строится полностью на кастомном коде: SDK на фронтенде регистрирует токен устройства, PHP-бэкенд отправляет уведомления через FCM HTTP v1 API.

FCM HTTP v1 API vs Legacy API

Google отключил Legacy HTTP API (ключ server key) в июне 2024. Все новые интеграции используют HTTP v1 API с авторизацией через OAuth 2.0 Service Account. Если в проекте осталась старая интеграция через https://fcm.googleapis.com/fcm/send — она уже не работает.

HTTP v1 endpoint: POST https://fcm.googleapis.com/v1/projects/{project_id}/messages:send

Авторизация — Bearer-токен, получаемый из Service Account JSON через Google Auth Library.

Service Account и авторизация

В Firebase Console → Project Settings → Service Accounts → Generate new private key. Скачиваем JSON-файл, кладём вне webroot:

/var/www/site/storage/firebase/service-account.json

Токен получаем через JWT:

use Google\Auth\Credentials\ServiceAccountCredentials;

class FcmAuthService
{
    private ServiceAccountCredentials $credentials;

    public function __construct(string $serviceAccountPath)
    {
        $this->credentials = new ServiceAccountCredentials(
            'https://www.googleapis.com/auth/firebase.messaging',
            json_decode(file_get_contents($serviceAccountPath), true)
        );
    }

    public function getAccessToken(): string
    {
        $token = $this->credentials->fetchAuthToken();
        return $token['access_token'];
    }
}

Устанавливаем зависимость: composer require google/auth. Токен кешируем — он действует 1 час. Перегенерация при каждом запросе — расточительство.

public function getCachedToken(): string
{
    $cacheKey = 'fcm_access_token';
    $cached   = \Bitrix\Main\Data\Cache::createInstance();

    if ($cached->initCache(3500, $cacheKey, '/fcm/')) {
        return $cached->getVars()['token'];
    }

    $token = $this->getAccessToken();
    $cached->startDataCache();
    $cached->endDataCache(['token' => $token]);

    return $token;
}

Регистрация FCM-токена на фронтенде

import { initializeApp } from 'firebase/app';
import { getMessaging, getToken, onMessage } from 'firebase/messaging';

const app = initializeApp({
    apiKey: "...",
    authDomain: "project.firebaseapp.com",
    projectId: "project-id",
    messagingSenderId: "123456789",
    appId: "1:123456789:web:abc"
});

const messaging = getMessaging(app);

// Запрашиваем разрешение и регистрируем токен
async function initPush() {
    try {
        const token = await getToken(messaging, {
            vapidKey: 'YOUR_VAPID_KEY'
        });

        if (token) {
            await fetch('/local/api/fcm/register', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Bitrix-Csrf-Token': BX.bitrix_sessid()
                },
                body: JSON.stringify({ fcm_token: token, platform: 'web' })
            });
        }
    } catch (err) {
        console.warn('Push permission denied:', err);
    }
}

// Обработчик foreground-уведомлений (когда вкладка открыта)
onMessage(messaging, (payload) => {
    new Notification(payload.notification.title, {
        body: payload.notification.body,
        icon: '/local/templates/main/images/push-icon.png'
    });
});

Для background-уведомлений нужен Service Worker /firebase-messaging-sw.js в корне сайта:

importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js');

firebase.initializeApp({ /* конфиг */ });
const messaging = firebase.messaging();

messaging.onBackgroundMessage((payload) => {
    self.registration.showNotification(payload.notification.title, {
        body: payload.notification.body,
        data: payload.data,
    });
});

Хранение FCM-токенов

class FcmTokenTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'local_fcm_tokens'; }

    public static function getMap(): array
    {
        return [
            new \Bitrix\Main\ORM\Fields\IntegerField('ID',       ['primary' => true, 'autocomplete' => true]),
            new \Bitrix\Main\ORM\Fields\IntegerField('USER_ID'),
            new \Bitrix\Main\ORM\Fields\StringField('TOKEN',     ['required' => true]),
            new \Bitrix\Main\ORM\Fields\StringField('PLATFORM'), // web, android, ios
            new \Bitrix\Main\ORM\Fields\DatetimeField('CREATED_AT'),
            new \Bitrix\Main\ORM\Fields\DatetimeField('LAST_USED_AT'),
            new \Bitrix\Main\ORM\Fields\StringField('ACTIVE'),
        ];
    }
}

При обновлении токена (FCM меняет токен при переустановке приложения) — поиск по старому токену и замена, а не дублирование записи.

Отправка уведомления

class FcmService
{
    private FcmAuthService $auth;
    private string $projectId;

    public function sendToUser(int $userId, string $title, string $body, array $data = []): void
    {
        $tokens = FcmTokenTable::getList([
            'filter' => ['USER_ID' => $userId, 'ACTIVE' => 'Y'],
            'select' => ['TOKEN', 'PLATFORM'],
        ])->fetchAll();

        foreach ($tokens as $tokenRow) {
            $this->sendToToken($tokenRow['TOKEN'], $title, $body, $data, $tokenRow['PLATFORM']);
        }
    }

    private function sendToToken(string $token, string $title, string $body, array $data, string $platform): void
    {
        $message = [
            'token'        => $token,
            'notification' => ['title' => $title, 'body' => $body],
            'data'         => array_map('strval', $data), // FCM требует строки
        ];

        // Платформо-специфичные настройки
        if ($platform === 'android') {
            $message['android'] = [
                'priority'     => 'high',
                'notification' => ['channel_id' => 'orders', 'icon' => 'ic_notification'],
            ];
        } elseif ($platform === 'ios') {
            $message['apns'] = [
                'headers' => ['apns-priority' => '10'],
                'payload' => ['aps' => ['sound' => 'default', 'badge' => 1]],
            ];
        }

        $accessToken  = $this->auth->getCachedToken();
        $projectId    = $this->projectId;
        $url          = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send";

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => json_encode(['message' => $message]),
            CURLOPT_HTTPHEADER     => [
                'Content-Type: application/json',
                "Authorization: Bearer {$accessToken}",
            ],
        ]);

        $response   = json_decode(curl_exec($ch), true);
        $httpCode   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode === 404 || ($response['error']['code'] ?? 0) === 404) {
            // Токен устарел — деактивируем
            FcmTokenTable::updateByToken($token, ['ACTIVE' => 'N']);
        }
    }
}

Топики vs индивидуальные токены

FCM поддерживает отправку по топикам (/topics/promo_electronics) — удобно для массовых рассылок без хранения токенов. Подписка на топик:

POST https://iid.googleapis.com/iid/v1:batchAdd
{
    "to": "/topics/promo_electronics",
    "registration_tokens": ["TOKEN1", "TOKEN2"]
}

Для транзакционных уведомлений (заказы конкретного пользователя) — только индивидуальные токены.

Сроки

Задача Срок
Service Account, FCM HTTP v1 клиент, кеш токена 2–3 дня
Регистрация токенов (web + android/ios) 3–4 дня
Отправка по событиям заказов + обработка ошибок 2–3 дня
Service Worker, foreground/background уведомления 2–3 дня
Управление подпиской из ЛК, топики 3–5 дней
Полный комплекс 3–4 недели