Интеграция 1С-Битрикс с OneSignal (push-уведомления)
Push-уведомления через браузер и мобильные приложения — один из немногих бесплатных каналов прямой коммуникации с пользователем. OneSignal предоставляет SDK для web push, iOS и Android, аналитику и сегментацию. В 1С-Битрикс нет встроенной поддержки OneSignal, поэтому интеграция строится на уровне: подписка браузера → OneSignal → PHP API → событие в Битрикс.
Архитектура интеграции
Браузер пользователя
→ OneSignal SDK (подписка, получение player_id)
→ POST /local/api/onesignal/register (сохраняем player_id в b_user)
→ Событие в Битрикс (заказ создан, доставка, скидка)
→ PHP → OneSignal REST API → push пользователю
player_id (или subscription_id в новом OneSignal SDK v2) — ключевой идентификатор устройства/браузера. Один пользователь может иметь несколько player_id (разные браузеры, устройства).
Подключение SDK на фронтенде
В <head> шаблона сайта или через менеджер тегов:
<!-- OneSignal Web Push SDK -->
<script src="https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.page.js" defer></script>
<script>
window.OneSignalDeferred = window.OneSignalDeferred || [];
OneSignalDeferred.push(async function(OneSignal) {
await OneSignal.init({
appId: "YOUR_ONESIGNAL_APP_ID",
safari_web_id: "web.onesignal.auto.YOUR_SAFARI_ID",
notifyButton: { enable: false }, // используем кастомную кнопку
allowLocalhostAsSecureOrigin: false,
});
// После разрешения — получаем subscription id и привязываем к пользователю
const subscription = await OneSignal.User.PushSubscription;
if (subscription.optedIn) {
await registerSubscription(subscription.id);
}
// Слушаем изменение статуса подписки
OneSignal.User.PushSubscription.addEventListener('change', async (event) => {
if (event.current.optedIn) {
await registerSubscription(event.current.id);
}
});
});
async function registerSubscription(subscriptionId) {
// Привязываем к авторизованному пользователю
await fetch('/local/api/onesignal/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Bitrix-Csrf-Token': BX.bitrix_sessid()
},
body: JSON.stringify({ subscription_id: subscriptionId })
});
}
</script>
Хранение подписок в Битрикс
Таблица local_push_subscriptions:
CREATE TABLE local_push_subscriptions (
ID BIGINT AUTO_INCREMENT PRIMARY KEY,
USER_ID INT,
SUBSCRIPTION_ID VARCHAR(200) NOT NULL UNIQUE,
PLATFORM ENUM('web','android','ios') DEFAULT 'web',
ACTIVE CHAR(1) DEFAULT 'Y',
CREATED_AT DATETIME,
LAST_USED_AT DATETIME,
INDEX idx_user (USER_ID)
);
USER_ID может быть NULL для неавторизованных посетителей — они идентифицируются по SUBSCRIPTION_ID. Неавторизованный пользователь потом авторизуется — нужно «подтянуть» анонимные подписки к его аккаунту.
// При авторизации (событие OnAfterUserAuthorize)
AddEventHandler('main', 'OnAfterUserAuthorize', function(array $fields) {
if (empty($fields['USER_ID'])) return;
// Ищем подписку по сессии, привязываем к пользователю
LocalPushSubscriptionTable::update(
['=USER_ID' => false], // NULL
['USER_ID' => $fields['USER_ID']]
);
// Упрощённо — в реальности нужно хранить subscription_id в сессии
});
Отправка push через OneSignal REST API
class OneSignalService
{
private string $appId;
private string $restApiKey;
private string $baseUrl = 'https://onesignal.com/api/v1';
public function sendToUser(int $userId, string $title, string $body, array $data = []): array
{
$subscriptions = LocalPushSubscriptionTable::getList([
'filter' => ['USER_ID' => $userId, 'ACTIVE' => 'Y'],
'select' => ['SUBSCRIPTION_ID'],
])->fetchAll();
if (empty($subscriptions)) {
return ['skipped' => 'no_subscriptions'];
}
$subscriptionIds = array_column($subscriptions, 'SUBSCRIPTION_ID');
return $this->send([
'app_id' => $this->appId,
'include_subscription_ids' => $subscriptionIds,
'headings' => ['en' => $title, 'ru' => $title],
'contents' => ['en' => $body, 'ru' => $body],
'data' => $data,
'web_url' => $data['url'] ?? '/',
'ttl' => 86400, // 1 день
]);
}
public function sendToSegment(string $segment, string $title, string $body, array $extra = []): array
{
return $this->send(array_merge([
'app_id' => $this->appId,
'included_segments' => [$segment],
'headings' => ['en' => $title, 'ru' => $title],
'contents' => ['en' => $body, 'ru' => $body],
], $extra));
}
private function send(array $payload): array
{
$ch = curl_init("{$this->baseUrl}/notifications");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"Authorization: Key {$this->restApiKey}",
],
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true) ?? [];
}
}
Точки отправки уведомлений в Битрикс
Смена статуса заказа:
AddEventHandler('sale', 'OnSaleStatusOrder', function(string $statusId, \Bitrix\Sale\Order $order) {
$messages = [
'P' => ['Заказ принят', 'Ваш заказ #' . $order->getField('ACCOUNT_NUMBER') . ' принят в обработку'],
'D' => ['Заказ отправлен', 'Ваш заказ передан в доставку'],
'F' => ['Заказ выполнен', 'Спасибо за покупку! Оставьте отзыв о товаре'],
];
if (!isset($messages[$statusId])) return;
[$title, $body] = $messages[$statusId];
$userId = (int)$order->getUserId();
(new OneSignalService())->sendToUser($userId, $title, $body, [
'url' => '/personal/order/detail/' . $order->getField('ACCOUNT_NUMBER') . '/',
'order_id' => $order->getId(),
]);
});
Брошенная корзина — через агент, запускаемый через 1 час после последнего добавления товара в корзину без оформления заказа.
Персональные акции — массовая отправка через sendToSegment() или таргетированная по пользовательским полям через OneSignal Filters API.
Управление подпиской из личного кабинета
Страница «Уведомления» в личном кабинете — переключатели по типам: статус заказа, акции, напоминания. Состояние хранится в пользовательских полях UF_PUSH_ORDER_STATUS, UF_PUSH_PROMO и т.д. Перед отправкой проверяем разрешение пользователя.
Обработка ошибок и очистка
OneSignal возвращает ошибки для невалидных subscription_id (пользователь отозвал подписку). При получении ошибки InvalidSubscriptionId — помечаем запись как ACTIVE = N.
Сроки
| Задача | Срок |
|---|---|
| Подключение SDK, сохранение subscription_id | 2–3 дня |
| Таблица подписок, привязка к пользователям | 1–2 дня |
| Отправка по событиям заказов | 2–3 дня |
| Брошенная корзина, управление подпиской из ЛК | 3–5 дней |
| Полный комплекс | 2–3 недели |







