Інтеграція 1С-Бітрікс із Firebase Cloud Messaging

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Інтеграція 1С-Бітрікс із Firebase Cloud Messaging
Середня
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • 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
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Інтеграція 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 тижні