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







