Заполнение множественного пользовательского свойства типа "строка" через API

Просмотров: 290

Задача: когда пользователь заходит в мобильное приложение, нужно сохранить FCM токен устройства в пользовательское поле "Токены устройств". Поле является множественной строкой - так как у пользователя может быть не одно устройство.

Множественное пользовательское свойство

Запись в пользовательское поле через API

Множественное поле имеет код UF_PUSH_DEVICE_TOKENS. Для записи в это поле можно воспользоваться API 1С-Битрикс:

$user = new CUser;
$userId = $USER->GetID();
$fields = ["UF_PUSH_DEVICE_TOKENS" => 'Значение'];
$user->Update($userId, $fields)

Но, нам нужно не просто добавить запись в поле но и сохранить предыдущие значения. Для реализации, лучше всего завернуть весь в функционал в компонент.

Пример компонента с получением токена устройства. Файл component.php:

if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

use Bitrix\Main\Loader;
use Bitrix\Main\UserTable;

Loader::includeModule("main");

global $USER;

if (
   $_SERVER['REQUEST_METHOD'] === 'POST' && 
   isset($_POST['token']) && 
   $USER->IsAuthorized()
) {
    $userId = $USER->GetID();
    $newToken = htmlspecialchars(trim($_POST['token']));

    // Получаем текущие значения поля UF_PUSH_DEVICE_TOKENS
    $arResult = UserTable::getList([
        'filter' => ['ID' => $userId],
        'select' => ['UF_PUSH_DEVICE_TOKENS']
    ])->fetch();

    $currentTokens = $arResult['UF_PUSH_DEVICE_TOKENS'];
    if (!is_array($currentTokens)) {
        $currentTokens = [];
    }

    // Проверяем, есть ли такой токен в массиве
    if (!in_array($newToken, $currentTokens)) {
        $currentTokens[] = $newToken;

        // Подготавливаем поля для обновления
        $fields = [
        	'UF_PUSH_DEVICE_TOKENS' => $currentTokens
        ];

        $user = new CUser;
        if ($user->Update($userId, $fields)) {
          // echo "Поле успешно обновлено.";
        } else {
          //  echo "Ошибка при обновлении поля: " . $user->LAST_ERROR;
        }
    } else {
       // echo "Токен уже существует.";
    }
    die(); // Завершаем выполнение скрипта после обработки AJAX-запроса
}

$this->includeComponentTemplate();
  • Здесь мы проверяем, авторизован ли пользователь, получаем все значения поля UF_PUSH_DEVICE_TOKENS и наполняем ими массив $currentTokens.
  • Если полученный токен отсутствует в этом массиве, то добавляем его в массив $currentTokens и обновляем поле UF_PUSH_DEVICE_TOKENS, перезаписывая все его значения с добавлением нового токена.

В коде выше мы получаем текущий токен устройства с помощью AJAX. Для получения и отправки токена используем FirebasePlugin.

Данная заметка является дополнением к Настройка push уведомлений через Firebase. Но подойдет как пример и для других задач в которых требуется обновлять пользовательские поля через API

Размещаем этот код в template.php. Здесь мы получаем токен и отправляем его AJAX-ом на эту же страницу (по факту на наш обработчик в component.php):

document.addEventListener('deviceready', onDeviceReady, false);

function onDeviceReady() {
    setTimeout(() => { // Не большая задержка нужна для iOS

        window.FirebasePlugin.getToken(function (token) {
            // alert(token); // Сохраняем этот токен в базе данных сайта
            // Отправляем токен на сервер
            $.ajax({
                url: '',
                type: 'POST',
                data: {
                    token: token
                },
                success: function (response) {
                    //console.log('Token saved successfully: ' + response);
                },
                error: function (xhr, status, error) {
                    //console.error('Error saving token: ' + error);
                }
             });
            }, function (error) {
                //console.log(error);
            });
     }, 100);
}

Ключевые моменты:

  • Проверка авторизации пользователя.
  • Получение текущих значений пользовательского поля.
  • Добавление нового токена в список, если его там нет.
  • Обновление пользовательского поля с новым списком токенов.

Этот подход обеспечивает сохранение всех токенов устройств пользователя и предотвращает дублирование токенов в базе данных.

Михаил Базаров 18.05.2024
В template.php стоит так же обвернуть скрипт проверкой на авторизацию пользователя:
Код
<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

if ($USER->IsAuthorized()) {?>
    <script>
        document.addEventListener('deviceready', onDeviceReady, false);
        function onDeviceReady() {
            setTimeout(() => {

                window.FirebasePlugin.getToken(function (token) {
                    // alert(token); // Сохраняем этот токен в базе данных сайта
                    // Отправляем токен на сервер
                    $.ajax({
                        url: '',
                        type: 'POST',
                        data: {
                            token: token
                        },
                        success: function(response) {
                            //console.log('Token saved successfully: ' + response);
                        },
                        error: function(xhr, status, error) {
                            //console.error('Error saving token: ' + error);
                        }
                    });
                }, function (error) {
                    //console.log(error);
                });
            }, 100);
        }
    </script>
<? } ?>

Либо, вообще, оставить template.php пустым, а скрипт подключить прямо в component.php
Код
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

use Bitrix\Main\Loader;
use Bitrix\Main\UserTable;

Loader::includeModule("main");

global $USER;

if ($USER->IsAuthorized()) {
  $path = $this->GetPath();
    ?>
    <script src="<?=$path?>/script.js"></script>
<?if (
     $_SERVER['REQUEST_METHOD'] === 'POST' &&
     isset($_POST['token'])
) {
    $userId = $USER->GetID();
    $newToken = htmlspecialchars(trim($_POST['token']));

    ... ОСТАЛЬНОЙ КОД ...

    die(); // Завершаем выполнение скрипта после обработки AJAX-запроса
}

} // end if ($USER->IsAuthorized()) 

$this->includeComponentTemplate();