Расширение описания API

Расширение описание документации сервиса.

Дерево условий скидок

Передача и хранение

Дерево условий скидок хранится отдельно для каждой скидки. Дерево представляет собой рекуррентную структуру, состоящую из узлов трех типов:

Начальным корневым узлом структуры может быть только группа условий. Внутри группы могут находиться только контейнеры условий, а уже в контейнерах условий содержатся массивы условий.

изображение_2025-02-07_124953704.png

Дерево описывается вложенными узлами, с указанием соответствующего типа объекта:

"type": "group", // Определяет тип объекта
"container": {
	// Состав полей зависит от типа объекта (см. ниже)
}

Каждый объект имеет свою структуру полей. При разборе объектов сервис выполняет отложенный разбор поля container, в зависимости от типа указанного в поле type

Группа условий

Определяет взаимодействие вложенных результатов вычисленных условий.

{
  "type": "group",
  "container": {
    "rule": "max", // Правило взаимодействия значений скидки подчиненных элементов
    "operator": "or", // Правило взаимодействия срабатывания подчиненных элементов
    "items": [] // Подчиненные элементы - группы или контейнеры условий
}

Контейнер условий

Определяет множество условий, значение скидки при срабатывании контейнера и правило взаимодействия сработавших скидок внутри контейнера.

{
  "type": "conditions",
  "container": {
    "rule": "and", // Правило взаимодействия условий
    "value": 1.5, // Значение скидки, переопределяющее основное значение
    "conditions": [] // Набор условий контейнера
}

Условие

Определяет утверждение, при срабатывании которого условие считается выполненным.

{
   "type":"some-type", // Тип условия, от типа зависит состав полей объекта `container`
   "container": {} // Объект описывающий состав условия, зависит от типа условия(см. ниже)
}

Типы условий

Булево

Описывает простое булево условие, если значение в поле `operand` == true, условие считается всегда выполненным, в противном случае не выполненным.

{
  	"type":"boolean,
  	"container": {
  		"operand": true
	} 
}

Уровень карты

Выполняется, если уровень карты равен или не равен установленному

{
  	"type":"card-level",
  	"container": {
  		// Оператор
  		"operator":"==",
  		// Идентификатор уровня карт
  		"operand": 1
	} 
}

Номер позиции

Выполняется, если номера позиций чека соответствуют условию

{
  	"type":"row-number",
  	"container": {
  		// Оператор
  		"operator":"==",
  		// Номер строки
  		"operand": 1
	} 
}

Дни недели

Выполняется, если дата документа выпадает на указанные в маске дни недели

{
  	"type":"week-day",
  	"container": {
  		// Маска дней недели, каждый бит отвечает за день недели пн-вс слева направо
  		"operand": "0010101"
	} 
}

День рождения

Выполняется, если день рождения клиента попадает в диапазон дат от даты документа

{
  	"type":"birthday",
  	"container": {
  		// Период перед днем рождения в днях, когда скидка может сработать
  		"days_before": 2,
     	 // Период после дня рождения в днях, когда скидка может сработать
      	"days_after": 2
	} 
}

Сумма без учета скидки

Выполняется, если сумма без учета скидки соответствует условию. Возможно уточнение сегмента товаров, для которого условие будет проверяться

{
  	"type":"sum-without-discounts",
  	"container": {
  		"area":"document|position",
      	"operator":">=",
  		"operand": 100.50,
      	"segments": [1, 2, 3, 4]
    } 
}

Сумма c учетом скидки

Выполняется, если сумма с учетом скидок соответствует условию. Возможно уточнение сегмента товаров, для которого условие будет проверяться

{
  	"type":"sum-with-discounts",
  	"container": {
  		"area":"document|position",
      	"operator":">=",
  		"operand": 100.50,
      	"segments": [1, 2, 3, 4]
    } 
}

Количество товара

Выполняется, если количество товара соответствует условию. Возможно уточнение сегмента товаров, для которого условие будет проверяться

{
  	"type":"quantity",
  	"container": {
  		"area":"document|position",
      	"operator":">=",
  		"operand": 100.50,
      	"segments": [1, 2, 3, 4]
    } 
}

Первая покупка по карте

Выполняется, текущий документ первый по карте

{
  	"type":"first-purchase",
  	"container": {
  		"operand": true
    } 
}

Сумма покупок по карте

Выполняется, если сумма покупок по карте соответствует условию

{
  	"type":"card-purchase-sum",
  	"container": {
      	"operator":">="
  		"operand": 100500.99
    } 
}

Группа ассортимента

Выполняется, если товар входит в группу ассортимента

{
  	"type":"catalog-group",
  	"container": {
      	"operator":"in"
      	// Идентификатор группа товаров
  		"operand": 42
    } 
}

Сумма покупок по карте за период

Выполняется, сумма покупок по карте за указанный период соответствует условию

{
  	"type":"card-purchase-sum-over",
  	"container": {
      	"operator":">",
  		"operand": 50000,
      	"step": "days|month|month-aligned|year|year-aligned|quarter-aligned",
      	"steps_before": 1,
      	"steps_after": 1
    } 
}

Комплект

Выполняется, если в документе есть комплекты

{
  	"type":"product-set",
  	"container": {
      	"price_sorting":"asc|desc",
  		"no_intersection": false,
      	"segments":[
          {
         	"id": 1,
          	"calculate": true,
          	"distribute":true,
			"quantity":10
          }
        ],
    } 
}

Группа промокодов

Выполняется, если промокод был передан и входит в группу

{
  	"type":"promo-group",
  	"container": {
  		"operand": 1 // Идентификатор группы промокодов
    } 
}

Маска промокода

Выполняется, если промокод подходит под переданную маску. Возможно использование регулярных выражений.

{
  	"type":"promo-mask",
  	"container": {
  		"operand": "%PROMO-202%" // Маска, символы % будут инерпретироваться как 0 или более любых символов
    } 
}

 

 

 

 

Двухфакторная авторизация операций

Описание механизма

Методы использующие двухфакторное подтверждение операций отмечены в документации красным тэгом 2FA.

В качестве второго фактора выступает фактор владения покупателем частного ресурса(телефон, почта). Настройка 2FA выполняется в личном кабинете и состоит из двух частей:

image-1741593780235.png

Каждое событие проверяется отдельно. Попытка отправки кода выполняется через канал в порядке указания его в списке каналов, в зависимости от наличия канала в конкретном запросе или в профиле клиента.

Пример: Установлена настройка проверки фактора владения при регистрации клиента. Порядок каналов отправки: Телефон -> Почта. В запросе регистрации телефон не передан, но есть адрес электронной почты. При таких вводных отправка кода будет выполняться на почту, т.к. определить телефон не представляется возможным. При тех же настройках и выполнении запроса идентификации клиента, если в карточке клиента есть телефон, отправка произойдет на телефон, как более приоритетный канал отправки.

Описание протокола

Протокол построен на сессионной модели. Любой защищенный запрос(запрос требующий 2FA) при установленной настройке для соответствующей операции будет начинать сессию работы с пользователем в определенном магазине.

Если для защищенного метода установлена настройка и список каналов отправки не пустой, выполняется проверки:

{
  "success": true,
  "message": "OK",
  "data": {
    "session": {
      "id": "081ff88e5d1f925d33926fb0f580e49485fd231b", // Идентификатор сессии
      "issuer": "79030000001",
      "issuer_location": "",
      "confirmed": false,
      "created_at": null,
      "updated_at": null
    },
    "instruction": {
      "channel": "phone", // Канал, на который выполнилась отправка кода подтверждения
      "reciever": "79030000001", // Идентификатор получателя(зависит от канала)
      "secret": "dummy-secret", // Секрет клиентского приложения, используется для проверки введенного кода подтверждения
      "duration": 120, // Время жизни кода подтверждения в секундах
      "available_channels": [ // Доступные в текущем контексте каналы отправки кодов подтверждения
        "phone"
      ]
    }
  }
}

Таким образом начинаться сессия может любым методом, подтверждаться любым методом, любой метод в цепочке вызовов после подтверждения больше не требует подтверждения.

@startuml !theme aws-orange  participant "Покупатель" as buyer participant "Интеграционный модуль" as module participant "Сервис" as service  module -> service ++#yellow: Первый запрос в сессии  service->module: Инструкции + (x-totp-session-id, x-totp-secret) service-[#green]->buyer: x-totp-code service-[#green]->module: x-totp-session-id  buyer-[#green]->module: Называет код  module->service: Повторный запроса + (x-totp-code, x-totp-secret, x-totp-session-id)  service->service: Валидирует код activate service #green service->service: Выполняет операцию  service -> module: Возвращает результат повторного запроса  module -> service: Последующие запросы в сессии + (x-totp-session-id) service -> service: Сессия подтверждена? service -> module: Результат последующих операций  module -> service: Последняя операция в сессии + (x-totp-session-id, x-totp-expire) service -> service: Завершить сессию deactivate service deactivate service service -> module: Последний ответ в сессии  @enduml

Описание развертывания

Сервис использует переменные окружения связанные с отправкой SMS4B. Также используются две переменные окружения:

TOTP_SESSION_TTL_MIN

Время жизни сессии подтвержденной сессии в минутах. Не менее 10 минут, если указано значение меньше - сессия будет жить 10 минут. Значение по-умолчанию: 10 минут.

TOTP_SESSION_VACUUM_INTERVAL_MIN

Интервал, с которым сервис выполняет очистку просроченных сессий. Не менее 10 минут, если указано значение меньше - сессия будет жить 10 минут. Значение по-умолчанию: 10 минут.