This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Шаблоны

Шаблоны позволяют генерировать как однострочные команды, так и целые блоки текста. Эти механизмы являются основой построения взаимодействий SHM.

Шаблоны служат:

Введение

Синтаксис: {{ ОБЪЕКТ.ДАННЫЕ }}

Например, с помощью объекта user можно получить доступ к данным пользователя:

  • user.id - идентификатор пользователя
  • user.login - логин пользователя
  • user.balance - баланс пользователя

Используя эти функции мы можем написать такой шаблон:

Уважаемый клиент.
Ваш логин: {{ user.login }}
Ваш баланс: {{ user.balance }} руб.

В шаблонах поддерживаются условия и циклы, примеры использования вы можете увидеть здесь: Прогноз оплаты

Больше информации о шаблонизаторе Вы можете узнать здесь

Объекты и функции

Ниже приведен список методов для работы с SHM через шаблоны.

Достуность тех или иных методов зависит от контекста применения шаблона.

Подробнее о доступности методов описано здесь.

Пользователь

Метод Описание
user.id() Идентификатор пользователя (получить/установить)
user.switch( USER_ID ) Переключение пользователя на указанного (смена контекста)
user.login Логин пользователя
user.balance Баланс пользователя
user.credit Кредитный лимит пользователя
user.dogovor Договор пользователя
user.full_name ФИО пользователя
user.settings Получить settings пользователя
user.set_settings({ 'foo' => 1 }) Сохранить в settings пользователя произвольные данные
user.services Ссылка на услуги пользователя
user.gen_session.id Специальная функция для генерации идентификатора сессии
user.set_new_passwd Смена пароля пользователя. Вернет новый пароль
user.pays. Ссылка на платежи пользователя
user.delete Удаление пользователя (с нулевым балансом, без услуг)
user.list_for_api( 'admin', 1) Получить всех пользователей

Услуги пользователя

Метод Описание
us.id() Идентификатор пользовательской услуги (получить/установить)
us.name Имя пользовательской услуги
us.created Дата создания пользовательской услуги
us.expire Дата истечения пользовательской услуги
us.status Статус пользовательской услуги
us.settings Получить параметры пользовательской услуги
us.set_settings({ 'foo' => 1 }) Сохранить в settings услуги пользователя произвольные данные
us.set(FIELD, VALUE) Установка поля FIELD в значение VALUE. Пример: us.set('next', 123)
us.child_by_category(CATEGORY). Ссылка на дочернюю услугу определенной категории
us.finish( 'money_back', 1) Завершение услуги с возвратом средств (биллинг продлит или заблокирует услугу в зависимости от наличия средств)
us.block Принудительная блокировка услуги пользователя
us.activate Активация услуги пользователя после блокировки
us.delete Удаление заблокированной услуги пользователя
us.gen_store_pass Специальная функция для генерации и сохранения пароля в settings
us.parent. Ссылка на родительскую услугу пользователя
us.top_parent. Ссылка на самую верхнюю услугу пользователя
us.service. Ссылка на каталог услуг
us.withdraw. Ссылка на списание услуги
us.list_for_api() Получение списка услуг пользователя

Каталог услуг

Метод Описание
service.id() Идентификатор пользовательской услуги (получить/установить)
service.name Название услуги
service.cost Базовая стоимость услуги
service.period Период услуги
service.category Категория услуги
service.server Ссылка на сервер услуги
service.id( N ).name Получение имени услуги c идентификатором N
service.id( N ). Получение произвольного поля услуги c идентификатором N
service.api_price_list() Возвращает массив услуг из каталога
service.settings Получить settings услуги
service.set_settings({ 'foo' => 1 }) Сохранить в settings услуги произвольные данные
service.withdraw. Ссылка на объект списания
service.create_for_api( 'service_id', N ) Регистрирует услугу клиенту с идентификатором N
service.list_for_api() Получение списка услуг из каталога

Платежи

Метод Описание
pay.id() Получить/установить id платежа
pay.date Дата и время платежа
pay.money Cумма платежа
pay.pay_system_id Имя платежной системы
pay.comment Данные платежа
pay.last Получить ссылку на последний платеж
pay.forecast Возвращает JSON прогноза оплат услуг
pay.paysystems Получить список платежных систем
pay.list_for_api() Получение списка платежей

Списания

Метод Описание
wd.id() Получить/установить id списания
wd.create_date Дата создания списания
wd.withdraw_date Дата списания списания
wd.cost Сумма
wd.discount Скидка
wd.bonus Кол-во бонусов
wd.months Период услуги
wd.total Итоговая стоимость
wd.service_id идентификатор каталога услуг
wd.user_service_id идентификатор услуги пользователя
wd.qnt Кол-во единиц товара
wd.list_for_api() Получение списка списаний

Сервера

Метод Описание
server.id() Получить/установить id сервера
server.name Имя сервера
server.host Host сервера
server.transport Транспорт сервера
server.settings Получение settings текущего сервера
server.set_settings({ 'foo' => 1 }) Сохранить в settings сервера произвольные данные
server.group. Ссылка на группу сервера
server.servers_by_group_id( N ) Получение списка серверов из группы N
server.list_for_api() Получение списка серверов

Группы серверов

Метод Описание
sg.id() Получить/установить id группы серверов
sg.name Имя группы серверов
sg.type Способ выбора серверов (random,by-one,evenly)
sg.transport Транспорт группы (local,ssh,http…)
sg.settings settings группы серверов
sg.set_settings({ 'foo' => 1 }) Сохранить в settings группы серверов произвольные данные
sg.list_for_api() Получение списка групп серверов

Шаблоны

Метод Описание
tpl.id Получить/установить id шаблона
tpl.id( NAME ).parse( 'usi', 123 ) Выполнить шаблон с именем NAME для пользовательской услуги с идентификаторм 123
tpl.data Данные шаблона
tpl.settings Получить settings шаблона

Хранилище

Метод Описание
storage.save( NAME, DATA ) Сохранить данные DATA в хранилище с ключем NAME
storage.load( NAME ) Получить данные из хранилища с ключем NAME
storage.del( NAME ) Удалить данные из хранилища с ключем NAME
storage.list_for_api() Получение списка данных

Конфигурация

Метод Описание
config.NAME Получить данные NAME из конфигурации

Telegram

Метод Описание
telegram.bot(TEMPLATE, CMD, [ARGS]) Выполнить CMD с аргументами ARGS из шаблона TEMPLATE

Задачи

Метод Описание
task Работа с задачами

Вспомогательные ф-ии

Метод Описание
params Аргументы вызова шаблона (http query string)
event_name Переменная содержит название текущего события
toJson() Функция преобразования объекта в JSON
toQueryString() Функция преобразования объектов в Query string
ref() Функция для преобразования данных в массив
list_for_api() Функция для получения списков данных из объекта

Примеры

1 - Использование методов

Ряд методов, описанных в разделе Шаблоны не будут работать в ряде случаев.

Работа с идентификаторами

Практически все методы поддерживают работу с идентификаторами (id).

Например, user.id вернет идентификатор текущего пользователя, а us.id вернет идентификатор текущей пользовательской услуги.

Если метод не возвращает свой id, то значит он небыл инициализирован, и следует “добираться” до метода либо через услугу пользователя, либо через явное указание идентификатора: id( N ). Например, в ряде случаев, server.id не вернет свой идентификатор, однако: us.service.server.id - вернет.

Помимо получения идентификатора, его можно и установить, пример: user.id(123) - вернет объект для пользователя с идентификатором 123.

  • user.login - вернет login текущего пользователя
  • user.id(123).login - вернет login пользователя 123
  • us.name - вернет название текущей услуги пользователя (если определена)
  • us.id(99).name - вернет название услуги пользователя с идентификатором 99

Контекст применения шаблонов

Метод Контекст
us.* События
us.id( N ).* Везде
us.withdraw Для платных услуг
us.service.server Для услуг, у которых определен сервер (server_id в settings услуги пользователя)
server.* События, Задачи, INIT сервера
server.id( N ) Везде
task События, Задачи

2 - Платежные системы

Описание

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

Получить список платежных систем можно:

  • Через Web: /shm/v1/user/pay/paysystems
  • Из шаблонов: pay.paysystems( АРГУМЕНТЫ )

Аргументы

Параметр Описание
user_id Идентификатор пользователя
amount Сумма платежа. По-умолчанию в неё записывается значение total из “Прогноз оплаты”
pp Proposed Payment (Предлагаемый платеж). Установите этот параметр в 1, если хотите, чтобы сумма платежа (amount) была установлена в ссылку shm_url
paysystem Укажите платежную систему, если хотите получить ссылку только для одной конкретной платежной системы

Описание полей

Пример ответа:

{
    "TZ": "Europe/Moscow",
        "data": [
        {
            "amount": 123,
            "forecast": 0,
            "name": "yookassa",
            "paysystem": "yookassa",
            "shm_url": "/shm/pay_systems/yookassa.cgi?action=create&user_id=1&ts=1706539331&amount=",
            "user_id": 1,
            "weight": 10
        },
        {
            "amount": 123,
            "forecast": 0,
            "name": "ЮMoney",
            "paysystem": "yoomoney",
            "shm_url": "/shm/pay_systems/yoomoney.cgi?action=create&user_id=1&ts=1706539331&amount=",
            "user_id": 1,
            "weight": 0
        }
        ],
        "date": "Mon Jan 29 17:42:11 2024",
        "items": 0,
        "limit": 25,
        "offset": 0,
        "version": "0.10.0"
}

Где:

  • paysystem - Платежная система
  • name - Произвольное название платежной системы (для отображения)
  • amount - Сумма платежа. По-умолчанию заполняется из “Прогноз оплаты”, если он положительный, или из переданного аргумента amount. В остальных случаях - пустой.
  • forecast - “Прогноз оплаты”
  • weight - “вес”. Используется для сортировки платежных систем
  • shm_url - Ссылка для выставления счета в платежной системе. Если флаг pp не установлен, то amount в ссылке остается пустой. Это сделано для удобства использования ссылки.

3 - Функции

toJson()

Преобразует объект в JSON.

Данную ф-ию удобно использовать для отладки запросов, когда не очевидно, что вернет тот или иной метод, для просмотра полей и т.п.

Пример 1:

Смотрим, что вернет метод user.list_for_api:

{{ toJson( user.list_for_api ) }}

Результат:

{
  "balance": 123.45,
  "block": 0,
  "bonus": 0,
  "can_overdraft": 0,
  "created": "2024-01-08 15:18:16",
  "credit": 0,
  "discount": 0,
  "full_name": "Admin",
  "last_login": "2024-01-22 20:52:53",
  "login": "admin",
  "user_id": 1
}

Пример 2:

Строим JSON объект. Удобно для использования в Telegram bot-е, в HTTP запросах и т.п.:

{{
  toJson(
    a = user.id
    b = 2
    c = [3,4,5]
  )
}}

Результат:

{"a":1,"b":2,"c":[3,4,5]}

toQueryString()

Преобразование объекта в Query String:

Пример:

{{
  toQueryString(
    a = user.id
    b = 2
    c = "hello world"
  )
}}

Результат:

a=1&b=2&c=hello%20world

list_for_api()

Метод для получения списка данных объекта.

Без аргументов выдаст первые 25 строк данных.

Аргументы:

Параметр Описание
admin Установка этого параметра в 1 позволяет получить данные всех клиентов
limit Кол-во отдаваемых данных. По-умолчанию: 25. (0 - без лимитов)
offset Индекс начала смещения списка. По-умолчанию: 0
filter Используется для поиска данных по определенным полям
sort_field Поле для сортировки (по-умолчанию ключевое поле)
sort_direction Порядок сортировки: asc, desc (по-умолчанию desc)

Пример 1:

Выведем всех пользователей:

{{ arr = ref(user.list_for_api('admin', 1)) }}
{{ FOR item IN arr }}
User id: {{ item.user_id }}, Login: {{ item.login }}, Balance: {{ item.balance }}
{{ END }}

Результат:

User id: 1, Login: admin, Balance: 0
User id: 22, Login: danuk, Balance: 224.44
User id: 34, Login: Dima, Balance: 0
User id: 117, Login: xims, Balance: 200

Пример 2:

Выведем список всех услуг с категорией начинающиеся на web, и период которых равен 1 месяцу:

{{ arr = ref(service.list_for_api('filter', { 'category' => 'web%', period => 1 } )) }}
{{ FOR item IN arr }}
Service id: {{ item.service_id }}, Name: {{ item.name }}, Cost: {{ item.cost }}
{{ END }}

Результат:

Service id: 111, Name: Web хостинг, Cost: 0
Service id: 110, Name: Тариф X-MAX, Cost: 300
Service id: 5, Name: Web хостинг LITE, Cost: 0

Сортировка

Существует два типа сортировки:

  • Сортировка на уровне запросов
  • Сортировка на уровне шаблона

При использовании пагинации важно сортировать результаты на уровне запросов.

Сортировка на уровне запросов

Сортировка на уровне запросов осуществляется непосредственно в БД.

Пример выдачи результатов отсортированных по возрастанию:

{{ arr = ref(service.list_for_api('sort_direction','asc')) }}

Пример выдачи результатов отсортированных по возрастанию по полю name:

{{ arr = ref(service.list_for_api('sort_direction','asc', 'sort_field','name')) }}

Сортировка в шаблонах

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

Для сортировки используете функции: sort (для алфавитной сортировки), nsort (для числовой сортировки) и reverse (обратный порядок данных).

Пример сортировки по полю category:

{{ arr = ref(service.list_for_api().sort('cateogry')) }}

Пример сортировки по полю cost, в убывающем порядке:

{{ arr = ref(service.list_for_api().nsort('cost').reverse) }}

4 - Автоматизации

4.1 - Подсчет доходов за месяц

Ниже приведен пример шаблона для подсчета поступления средств за Январь 2024 года:

{{ sum = 0 }}
{{ arr = ref(user.pays.list_for_api( 'admin', 1, 'limit', 0,  'filter', { 'date' => '2024-01-%'} )) }}
{{ FOR item IN arr }}
{{ sum = sum + item.money }}
{{ END }}

Итого за Январь: {{ sum }} руб.

4.2 - Рассылки

SHM умеет делать рассылки по всем пользователям.

Для того, чтобы сделать рассылку, необходимо:

  • В кабинете Администратора выбрать пункт меню: “Задачи -> Текущие задачи”, далее нажать кнопку “ADD”.
  • Выберите для кого сделать рассылку: для одного пользователя или для всех (при тестировании используйте одного конкретного пользователя)
  • Выберите группу серверов, которая будет использоваться для рассылки
  • Выберите необходимый шаблон
  • Создайте задачу
  • Контролируйте исполнение задчи в “Текущие задачи”

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

Примеры шаблонов

Шаблон для всех клиентов

Уважаемый {{ user.full_name }}!
Это тестовое сообщение.
Ваш личный кабинет находится по адресу: {{ config.cli.url }}

Шаблон для пользователей Telegram

Если рассылку делать с помощью транспорта Телеграм, то данная проверка в шаблоне смысла не имеет, так как транспорт Телеграм сам проверяет это поле.

{{ IF user.settings.telegram.login }}
Вы получили это сообщение потому, что у Вас есть Telegram.
Ваш Telegram логин: {{ user.settings.telegram.login }}
{{ END }}

Шаблон для услуг в определенной категории

Данный шаблон будет отправлен только клиентам, у которых есть услуги в категории test. Категорию услуг можно указать и через маску, например так: te%.

{{ IF user.services.list_for_api('category','test') }}
Уважаемый {{ user.full_name }}!
Вы получили это сообщение потому, что у Вас есть услуга в категории test.
{{ END }}

Информация об услугах в определенной категории

Показываем сообщение для каждой услуги в категории test.

{{ user_services = ref(user.services.list_for_api('category','test')) }}
{{ IF user_services }}
Услуги в категории test найдены в количестве: {{ user_services.size }} штук.

{{ FOR item IN user_services }}
Услуга: {{ item.name }}
Категория: {{ item.category }}
Статус: {{ item.status }}
Действует до: {{ item.expire }}

Цена: {{ item.withdraws.cost }}
Кол-во: {{ item.withdraws.qnt }}
Cкидка: {{ item.withdraws.discount }}%
Итого: {{ item.cost }}
{{ END }}

{{ END }}

Активная услуга в определенной категории

Перебираем (ищем) все услуги пользователя с категорией test, и проверяем, что статус активный. Как только активная услуга будет найдена, то пишем сообщение и прекращаем перебор (LAST). Таким образом, будет выведено только одно сообщение, даже если услуг несколько.

Если нужно выводить сообщения для каждой услуги, необходимо убрать LAST.

{{ FOR item IN ref(user.services.list_for_api('category','test')) }}

{{ IF item.status == 'ACTIVE' }}
Вы видите это сообщение, потому что у вас есть активная услуга в категории test
{{ LAST }}
{{ END }}

{{ END }}

Уведомление клиентам без услуг в определенной категории

{{ IF ref(user.services.list_for_api('category','test')).empty }}
Вы видите это сообщение, потому что у вас нет ниодной услуги в категории test
{{ END }}

Подробнее о создании и настройке шаблонов можно прочитать здесь

4.3 - Удаление услуг при блокировке

Для удаления услуг при блокировке создайте шаблон вида:

{{ IF us.status == 'BLOCK' }}
{{ us.delete }}
{{ END }}

и добавьте его к событию CHANGED для нужной категории услуг.

Каждый раз, когда услуга будет переходить в статус BLOCK, SHM будет удалять её.

4.4 - Массовое обновление тарифов

Бывают случаи, когда нужно обновить тарифы всем клиентам. Здесь приведены примеры, как это сделать.

Обновление стоимости текущей услуги (тарифа)

Просто изменить стоимость услуги в Каталоге не достаточно. Необходимо для таких услуг пользователя установить “следующую” услугу в “текущую”:

{{ arr = ref(user.services.list_for_api( 'admin',1, 'limit',0, 'filter',{} )) }}
{{ FOR item IN arr }}
{{ user = user.switch( item.user_id ) }}
{{ us.id( item.user_service_id ).set('next', item.service_id) }}
{{ END }}

Массовая смена услуг (тарифов)

Например, мы хотим сменить (со следующего учетного периода) услугу 5 на 6, делается это так:

{{ arr = ref(user.services.list_for_api( 'admin',1, 'limit',0, 'filter',{ 'service_id' => 5 } )) }}
{{ FOR item IN arr }}
{{ user = user.switch( item.user_id ) }}
{{ us.id( item.user_service_id ).set('next', 6) }}
{{ END }}

5 - Уведомления клиентам

Для отправки уведомлений клиентам создайте соответствующее событие и привяжите к нему шаблон.

Уведомления будут отправлены с помощью выбранного транспорта. Например, Вы можете отправить уведомление EMAIL, и/или Telegram (настраивается в событии).

5.1 - Прогноз оплаты

Описание

SHM имеет встроенный модуль forecast, позволяющий получать информацию о прогнозе оплаты услуг.

forecast находит все услуги (кроме уже заблокированных), дата истечения которых менее чем 3 дня (days), и ещё неоплаченные услуги, и вычисляет стоимость их продления.

Получить прогноз оплаты можно следующими способами:

  • Через Web для текущего авторизованного пользователя: /shm/v1/user/pay/forecast
  • Через Web для пользователя с ID 123: /shm/v1/user/pay/forecast?user_id=123 (нужно быть авторизованным под администратором)
  • Из шаблонов: user.pays.forecast

Настройки

Параметр Описание
days Кол-во дней для прогноза (3 дня по-умолчанию)
blocked Учитывать заблокированные услуги (0 - по-умолчанию НЕТ)

Пример команды в шаблонах:

{{ forecast = user.pays.forecast('days', 10, 'blocked', 1) }}

Пример шаблона

Метод user.pays.forecast возвращает JSON вида:

{
  "items": [
        {
            "name": "Регистрация домена в зоне .RU",
            "service_id": 11,
            "user_service_id": 2949,
            "usi": 2949,
            "cost": 590,
            "discount": 0,
            "months": 12,
            "qnt": 1,
            "total": 590,
            "expire": "2017-07-29 12:39:46",
            "status": "ACTIVE",
            "next": {
                "name": "Продление домена в зоне .RU",
                "service_id": 12,
                "cost": 890,
                "discount": 0,
                "months": 12,
                "qnt": 1,
                "total": 890
            }
        }
    ],
    "balance": -21.56,
    "bonuses": 100,
    "dept": 21.56,
    "total": 768.44
}

Мы можем построить шаблон письма о прогнозе опаты услуг следующим образом:

Уважаемый {{ user.full_name }}

Уведомляем Вас о сроках действия услуг:

{{ FOR item IN ref(user.pays.forecast.items) }}
- Услуга: {{ item.name }}
  {{ IF item.expire }}
  Истекает: {{ item.expire }}
  {{ IF item.service_id != item.next.service_id }}
  Следующая услуга: {{ item.next.name }}
  Стоимость: {{ item.next.total }}
  {{ ELSE }}
  Стоимость продления: {{ item.next.total }}
  {{ END }}
  {{ ELSE }}
  Стоимость: {{ item.total }}
  {{ END }}

{{ END }}

{{ IF user.pays.forecast.dept }}
Погашение задолженности: {{ user.pays.forecast.dept }}
{{ END }}

Итого к оплате: {{ user.pays.forecast.total }} руб.

Подробнее о создании и настройке шаблонов можно прочитать здесь

5.2 - Уведомление о зачислении платежа

Описание

Создайте шаблон со следующим содержимым и привяжите его к событию PAYMENT:

Ваш платеж на сумму {{ user.pays.last.money }} зачислен.

Баланс: {{ user.balance }}

6 - HTTP (API)

SHM позволяет использовать шаблоны для внешнего использования

Поддерживаемые методы:

  • GET
  • POST

HTTP адрес

Доступ к шаблону с именем my_template можно получить следующим способами:

Для пользователей

Доступ с авторизацией:

/shm/v1/template/my_template?format=html&foo=1&bar=hello

Пример для curl

curl -s -u 'admin:admin' http://127.0.0.1:8081/shm/v1/template/my_template

Более детально о вариантах аутентификации можно почитать здесь

Для публичного использования

/shm/v1/public/my_template?format=html&foo=1&bar=hello

Для того, чтобы шаблон работал без авторизации необходимо прописать в его settings параметр:

allow_public: true

В публичных шаблонах переменная user не устанавливается автоматически, но её можно установить самостоятельно:

  • Указать идентификатор вручную (статически):

    в шаблоне: {{ user = user.switch( 123 ) }}

  • Указать идентификатор через HTTP запрос:

    /shm/v1/public/my_template?uid=123

    в шаблоне: {{ user = user.switch( request.params.uid ) }}

Пример для curl

curl -s http://127.0.0.1:8081/shm/v1/public/my_template?uid=123

Пример шаблона для проверки существования пользователя:

{{ IF user.switch( request.params.uid ).id }}
...
{{ END }}

Аргументы

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

{{ foo = request.params.foo }}

Ниже приведен список специальных аргументов:

format - формат отдаваемого контента (MIME types)

  • plain (text/plain)
  • html (text/html)
  • json (application/json)
  • other (application/octet-stream)
  • qrcode

user_id - зарезервирован

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

HTTP заголовки

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

{{ headers = request.headers }}

Пример шаблона для проверки заголовка x-webhook-secret:

{{ IF request.headers.x-webhook-secret == 'something-very-very-secret' }}
...
{{ END }}

Примеры

6.1 - Вывод данных в формате HTML

Пример шаблона (my_template) для формирования данных в HTML:

<table border=1>
{{ FOR u IN ref( user.list_for_api('admin',1,'limit',0)) }}
<tr>
    <td>{{ u.user_id }}</td>
    <td>{{ u.login }}</td>
    <td>{{ u.balance }}</td>
</tr>
{{ END }}
</table>

Пример вызова шаблона для curl:

curl -s http://127.0.0.1:8081/shm/v1/public/my_template?format=html

Необходимо прописать в settings шаблона параметр: allow_public: true

Результат работы HTML шаблона лучше всего смотреть в браузере:

http://127.0.0.1:8081/shm/v1/public/my_template?format=html

6.2 - Вывод данных в формате JSON

Для формирования JSON объекта удобно использовать следующий синтаксис:

Пример шаблона (my_template) для формирования данных в JSON:

{{ u = user.id( request.params.uid ) }}
{{
  toJson({
    user_id = u.id
    login = u.login
    balance = u.balance
    last_payment = u.pays.last
    forecast = u.pays.forecast.total
  })
}}

Пример вызова шаблона для curl:

curl -s http://127.0.0.1:8081/shm/v1/public/my_template?format=json&uid=123

Необходимо прописать в settings шаблона параметр: allow_public: true

Пример результата:

{
    "user_id": "123",
    "login": "danuk",
    "balance": -21.56,
    "last_payment": {
        "comment": null,
        "date": "2016-01-04 20:33:35",
        "id": 2,
        "money": 455,
        "pay_system_id": "manual",
        "user_id": 123
    },
    "forecast": 1013.45
}

7 - Выполнение скриптов

Шаблоны позволяют генерировать как однострочные команды, так и целые блоки текста. Эти механизмы являются основой построения взаимодействий SHM.

8 - Telegram bot

Шаблон для Telegram Bot-а

Это двух-уровневый шаблон. Сначала используются теги <% ... %> для нахождения нужной секции шаблона, соответствующей команды. После нахождения нужной секции шаблонизатор будет использовать теги вида: {{ ... }}.

Для сопоставления команды пользователя/бота используется внутренняя переменная cmd. Так, при наборе команды /balance будет найдена секция: <% CASE '/balance' %>.

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

В каждой секции мы можем писать реальные команды Telegram. Например, команда sendMessage отправляет сообщение в Telegram. Вы можете использовать эту команду в соответсвии с документацией Telegram.

В каждой секции можно писать множество команд, через запятую (см. пример в секции /balance).

Для того, чтобы лучше понять, как строятся всевозможные кнопочки, читайте документацию Telegram. В этом шаблоне всего-лишь описаны вызовы этих методов.

Пример шаблона:

<% SWITCH cmd %>
<% CASE 'USER_NOT_FOUND' %>
{
    "shmRegister": {
        "partner_id": "{{ args.0 }}",
        "callback_data": "/menu",
        "error": "ОШИБКА"
    }
}
<% CASE ['/start', '/menu'] %>
{
    "sendMessage": {
        "text": "Я Ваш тестовый Telegram Bot",
        "reply_markup": {
            "inline_keyboard": [
                [
                    {
                        "text": "Баланс",
                        "callback_data": "/balance"
                    }
                ]
            ]
        }
    }
}
<% CASE '/balance' %>
{
    "deleteMessage": { "message_id": {{ message.message_id }} }
},
{
    "sendMessage": {
        "text": "Баланс: {{ user.balance }}",
        "reply_markup": {
            "inline_keyboard": [
                [
                    {
                        "text": "Назад",
                        "callback_data": "/menu"
                    }
                ]
            ]
        }
    }
}

Стандартные методы Telegram

В SHM можно использовать любые методы Telegram.

Полный перечень доступных методов и синтаксис их использования можно посмотреть на официальном сайте документации Telegram https://core.telegram.org/bots/api#available-methods

chat_id - заполняется автоматически, но при необходимости его можно указать

Встроенные переменные SHM

  • cmd - специальная переменная SHM в которую записывается значение, полученное из Telegram, в зависимости от типа: message.text для команд введеных пользователем, и callback_query.data для callback_data. Если команда пользователя начинается с символа /, то такая команда будет усечена до первого слова.
  • args - массив аргументов команды, разделитель - пробел.
  • message - полное сообщение от Telegram (json объект)

Примеры парсинга cmd и args:

Источник Команда cmd args
Пользователь /test 1 2 3 /test [1,2,3]
Пользователь test 1 2 3 test 1 2 3 [1,2,3]
callback_data /test 1 2 3 /test [1,2,3]
callback_data test 1 2 3 test [1,2,3]

args - это массив. Для получения значений из него используйте синтаксис: args.N, где N - индекс элемента. Например, получить первый элемент массива можно так: args.0

Встроенные методы SHM

  • shmRegister - метод позволяет зарегистрировать нового клиента

    "shmRegister": {
        "callback_data": "/menu",
        "error": "ОШИБКА",
        "partner_id": 123
    }
    

    где: partner_id - ID партнера, для реферальной программы (опционально).

  • shmServiceOrder - метод для регистрации новых услуг. Пример использования:

    "shmServiceOrder": {
        "service_id": "{{ args.0 }}",
        "callback_data": "/menu",
        "cb_not_enough_money": "/pay",
        "error": "ОШИБКА"
     }
    

    где: service_id - ID услуги, callback_data - команда для случая успешного заказа услуги, cb_not_enough_money - команда для случая нехватки средств для активации услуги.

  • shmServiceDelete - метод для удаления услуг пользователя. Пример использования:

    "shmServiceDelete": {
        "usi": "{{ args.0 }}",
        "callback_data": "/menu",
        "error": "ОШИБКА"
     }
    

    где: usi - ID услуги пользователя

  • uploadDocumentFromStorage - метод загружает данные из Storage и отправляет их в виде файла

    "uploadDocumentFromStorage": {
        "name": "{{ args.0 }}",
        "filename": "{{ args.0 }}.conf"
    }
    
  • uploadPhotoFromStorage - метод загружает данные из Storage и отправляет их в виде картинки (QR code)

    "uploadPhotoFromStorage": {
        "name": "{{ args.0 }}",
        "format": "qr_code_png"
    }
    

Приём платежей

Для приёма платежей в Telegram удобно использовать дополнительный шаблон (web_app).

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

  1. Настройте одну или несколько платежных систем
  2. Скачайте шаблон и сохраните в SHM под названием tg_payments
  3. В Шаблоне своего бота используйте конструкцию вида:
<% CASE '/payment' %>
{
  "sendMessage": {
    "text": "Оплата покупки",
    "reply_markup": {
      "inline_keyboard": [
        [
          {
            "text": "Оплатить...",
            "web_app": {
              "url": "{{ config.api.url }}/shm/v1/template/tg_payments?format=html&session_id={{ user.gen_session.id }}"
            }
          }
        ]
      ]
    }
  }
}

Авторизация пользователей

SHM автоматически авторизует пользователя. Для связки пользователя SHM и пользователя Telegram используется user_id из Telegram.

Для отправки сообщений пользователю в Telegram необходимо знать:

  • user_id - идентификатор пользователя Telegram
  • chat_id - идентификатор чата Telegram

Если пользователь хоть раз взаимодействовал с ботом, подключенным к SHM, то его user_id и chat_id автоматически сохраняются в settings пользователя.

chat_id определяется в следующем порядке:

  • Из сообщения Telegram (в случае, если клиент отправил команду боту)
  • Из settings шаблона (telegram.chat_id)
  • Из settings пользователя SHM (telegram.chat_id)

Отправка системных сообщений

В случае, если Вы хотите отправлять системные сообщения себе в телеграм, то для этого Вы можете создать отдельный шаблон, и в его settings прописать:

{
    "telegram": {
        "chat_id": ID_вашего_чата
    }
}

Пример шаблона:

Событие:  {{ event_name }}

Пользователь: {{ user.login }} ({{ user.id }})

{{ IF us.id }}
Услуга: [{{ us.id }}] {{ us.name }}
{{ END }}

{{ IF event_name == "PAYMENT" }}
Платеж на сумму: {{ user.pays.last.money }} зачислен для пользователя: {{ user.login }}
{{ END }}

8.1 - Пагинация

Пример шаблона для постраничного вывода списка услуг

{{
  limit = 5
  data = []
}}
<% SWITCH cmd %>
<% CASE '/list' %>
{{
  offset = args.0 || 0
  items = ref( user.services.list_for_api('limit',limit, 'offset',offset) )
}}
{{ FOR item IN items }}
{{ data.push(
    [{
      "text" = 'Услуга: ' _ item.name _ ' ID: ' _  item.user_service_id
      "callback_data" = '/service ' _ item.user_service_id
    }]
  )
}}
{{ END }}

{{ data.push(
    [{
      "text" = 'Еще...'
      "callback_data" = '/list ' _ (limit + offset)
    }]
  ) IF items.size == limit
}}

{
  "sendMessage": {
    "text": "Список услуг",
    "reply_markup" : {
      "inline_keyboard": {{ toJson( data ) }}
    }
  }
}
<% END %>