Сценарии работы с POS системой¶
Описание пошаговых сценариев работы кассовой системы с API Sagi для интеграции бонусной программы.
Визуальные схемы интеграции¶
Ниже представлены ключевые сценарии интеграции в виде диаграмм последовательности с указанием конкретных API-вызовов.
Начисление бонусов (без списания)¶
sequenceDiagram
participant POS as Касса (POS)
participant API as Sagi API
POS->>API: GET /api/v1/promoters/find?phone={phone}&branch_id={id}
API-->>POS: { id, first_name, tags, ... }
POS->>API: GET /api/v1/branches/{id}/private/balance?user_id={id}&group_id={id}
API-->>POS: 2500.50
POS->>API: GET /api/v1/branches/{id}/cashback?user_id={id}
API-->>POS: 5.0
Note over POS: Кассир завершает оплату
POS->>API: POST /api/v1/branches/{id}/cash/order
Note right of POS: { user_id, amount, bonus_amount: 0 }
API-->>POS: { id: order_id, status: "CREATED" }
POS->>API: POST /api/v1/orders/{order_id}/cash/complete
Note right of POS: { use_balance: false, payment_method: "card" }
API-->>POS: 200 OK
Note over API: Кэшбек начислен на баланс клиента
Списание бонусов с кодом подтверждения¶
sequenceDiagram
participant POS as Касса (POS)
participant API as Sagi API
participant Кл as Клиент (SMS)
POS->>API: GET /api/v1/promoters/find?phone={phone}&branch_id={id}
API-->>POS: { id, send_code_for_use_cashback: true, ... }
POS->>API: GET /api/v1/branches/{id}/private/balance?user_id={id}&group_id={id}
API-->>POS: 2500.50
Note over POS: Кассир выбирает "списать 1000 бонусов"
POS->>API: POST /api/v1/customers/{user_id}/send-use-cashback-code
Note right of POS: { branch_id }
API->>Кл: SMS: "Ваш код: 1234"
API-->>POS: "1234"
Note over POS: Кассир вводит код от клиента
POS->>API: POST /api/v1/branches/{id}/cash/order
Note right of POS: { user_id, amount: 2000,<br/>bonus_amount: 1000,<br/>use_balance_code: "1234" }
API-->>POS: { id: order_id }
POS->>API: POST /api/v1/orders/{order_id}/cash/complete
Note right of POS: { use_balance: true, amount: 1000,<br/>payment_method: "mixed" }
API-->>POS: 200 OK
Выдача награды (штампы)¶
sequenceDiagram
participant POS as Касса (POS)
participant API as Sagi API
POS->>API: GET /api/v1/branches/{id}/customers/{user_id}/award
API-->>POS: { stamp_count: 10, received_stamp_count: 10, is_active: true }
Note over POS: Штампов достаточно — показать "Выдать награду"
POS->>API: POST /api/v1/branches/{id}/cash/order
Note right of POS: { user_id, amount: 2000,<br/>give_award: true }
API-->>POS: { id: order_id }
POS->>API: POST /api/v1/branches/{id}/awards/{award_id}/give
Note right of POS: { user_id, stamp_count: 10 }
API-->>POS: { received_stamp_count: 0, total: 4 }
POS->>API: POST /api/v1/orders/{order_id}/cash/complete
Note right of POS: { use_balance: false, payment_method: "card" }
API-->>POS: 200 OK
Note over API: Штампы сброшены, награда выдана
Первоначальная настройка (выполняется один раз)¶
1. Подключение приложения к Sagi¶
- Авторизация: Запросите логин и пароль у бизнеса, выполните запрос к
/api/v1/auth/business - Получение филиала: Из ответа авторизации сохраните первый элемент массива
branchesкакbranch_id - Получение Group ID: Вызовите
/api/v1/branches/{branch_id}для полученияgroup_idфилиала - Настройка товара-подарка: Для каждого заведения настройте товар-подарок (нулевой стоимости) для программы наград
- Автоматическое обновление токенов: Настройте cron-задачу для вызова
/api/v1/auth/refresh_token
Что сохранить в памяти:
- access_token - JWT токен
- branch_id - ID филиала
- group_id - Group ID филиала
- gift_product_id - ID товара-подарка
- role - роль пользователя (для определения прав доступа)
Сценарий 1: Начисление бонусов (без списания)¶
Начало работы смены¶
При запуске кассы проверьте:
1. Наличие действительного токена (если истек - обновите)
2. Статус программы наград в филиале (проверьте configuration.award.enabled)
При переходе к оплате чека¶
Шаг 1: Запрос телефона клиента¶
Шаг 2: Поиск клиента и получение информации¶
# 1. Найти клиента
GET /api/v1/promoters/find?phone={phone}&branch_id={branch_id}
# 2. Получить баланс в филиале
GET /api/v1/branches/{branch_id}/private/balance?user_id={user_id}&group_id={group_id}
# 3. Получить процент кешбека
GET /api/v1/branches/{branch_id}/cashback?user_id={user_id}
# 4. Получить информацию о штампах (если награды включены)
GET /api/v1/branches/{branch_id}/customers/{user_id}/award
Шаг 3: Отображение информации кассиру¶
╔══════════════════════════════════════╗
║ Клиент: Иван Иванов ║
║ Телефон: +77071234567 ║
║ Баланс бонусов: 2,500 тенге ║
║ Кешбек: 5% (макс. 100 тенге) ║
║ Штампы: 7 из 10 для награды ║
║ ║
║ □ Начислить штампики [1] шт ║
║ ║
║ Покупка: 2,000 тенге ║
║ Будет начислено: 100 тенге ║
╚══════════════════════════════════════╝
Шаг 4: Обработка штампиков¶
- Если
received_stamp_count==stamp_count→ показать кнопку "Выдать награду" - Иначе → показать checkbox "начислить штампики" с полем ввода количества
- При выборе начисления штампиков проверить:
текущие + начисляемые >= требуемых→ показать кнопку "Выдать награду"
После завершения оплаты¶
Шаг 5: Создание транзакции¶
POST /api/v1/branches/{branch_id}/cash/order
{
"user_id": 1460220481801031680,
"amount": 2000,
"bonus_amount": 0,
"comment": "Покупка в кассе #1",
"user_phone": "+77077000087",
"add_stamp": true,
"stamp_count": 1,
"give_award": false
}
Шаг 6: Завершение транзакции¶
POST /api/v1/orders/{order_id}/cash/complete
{
"use_balance": false,
"amount": 0,
"payment_method": "card"
}
Информация в чеке¶
════════════════════════════════════════
КАФЕ "АРОМАТ"
════════════════════════════════════════
Товары: 2,000 тг
────────────────────────────────────────
ИТОГО К ОПЛАТЕ: 2,000 тг
Оплачено картой: 2,000 тг
════════════════════════════════════════
БОНУСНАЯ ПРОГРАММА SAGI:
• Начислены бонусы: 100 тг
• Добавлено штампиков: 1
• Штампов накоплено: 8/10
════════════════════════════════════════
Сценарий 2: Списание бонусов с кодом подтверждения¶
Шаги 1-3: Аналогично сценарию 1¶
Шаг 4: Отображение с возможностью списания¶
╔══════════════════════════════════════╗
║ Клиент: Иван Иванов ║
║ Баланс бонусов: 2,500 тенге ║
║ ║
║ Списать бонусы: [1000] тенге ║
║ Максимально: 2,500 тенге ║
║ ║
║ □ Начислить штампики [1] шт ║
║ ║
║ К доплате: 1,000 тенге ║
╚══════════════════════════════════════╝
Шаг 5: Отправка кода подтверждения (если требуется)¶
# Если send_code_for_use_cashback = true и bonus_amount > 0
POST /api/v1/customers/{user_id}/send-use-cashback-code
{
"branch_id": 1234567890123456
}
╔══════════════════════════════════════╗
║ Код подтверждения отправлен клиенту ║
║ на номер +77071234567 ║
║ ║
║ Введите код: [______] ║
╚══════════════════════════════════════╝
Шаг 6: Создание транзакции с кодом¶
POST /api/v1/branches/{branch_id}/cash/order
{
"user_id": 1460220481801031680,
"amount": 2000,
"bonus_amount": 1000,
"comment": "Покупка в кассе #1",
"user_phone": "+77077000087",
"add_stamp": true,
"stamp_count": 1,
"give_award": false,
"use_balance_code": "123456"
}
Шаг 7: Завершение со списанием¶
POST /api/v1/orders/{order_id}/cash/complete
{
"use_balance": true,
"amount": 1000,
"payment_method": "mixed"
}
Информация в чеке при списании¶
════════════════════════════════════════
КАФЕ "АРОМАТ"
════════════════════════════════════════
Товары: 2,000 тг
────────────────────────────────────────
Списано бонусов: -1,000 тг
К доплате: 1,000 тг
Оплачено картой: 1,000 тг
════════════════════════════════════════
БОНУСНАЯ ПРОГРАММА SAGI:
• Списано бонусов: 1,000 тг
• Начислены бонусы: 50 тг
• Добавлено штампиков: 1
════════════════════════════════════════
Сценарий 3: Выдача награды¶
При достаточном количестве штампов¶
Отображение кнопки "Выдать награду"¶
╔══════════════════════════════════════╗
║ Клиент: Иван Иванов ║
║ Штампы: 10 из 10 (готов) ║
║ ║
║ [ВЫДАТЬ НАГРАДУ] ║
║ "Бесплатный кофе" ║
║ ║
║ Покупка: 2,000 тенге ║
╚══════════════════════════════════════╝
При выдаче награды¶
# 1. Добавить товар-подарок в чек автоматически
# Товар с нулевой стоимостью
# 2. Создать транзакцию с выдачей награды
POST /api/v1/branches/{branch_id}/cash/order
{
"user_id": 1460220481801031680,
"amount": 2000,
"bonus_amount": 0,
"comment": "Покупка + награда",
"user_phone": "+77077000087",
"add_stamp": false,
"stamp_count": 0,
"give_award": true
}
# 3. Выдать награду
POST /api/v1/branches/{branch_id}/awards/{award_id}/give
{
"user_id": 1460220481801031680,
"stamp_count": 10
}
# 4. Завершить транзакцию
POST /api/v1/orders/{order_id}/cash/complete
{
"use_balance": false,
"amount": 0,
"payment_method": "card"
}
Чек с выдачей награды¶
════════════════════════════════════════
КАФЕ "АРОМАТ"
════════════════════════════════════════
Товары: 2,000 тг
ПОДАРОК: Кофе американо 0 тг
────────────────────────────────────────
ИТОГО К ОПЛАТЕ: 2,000 тг
Оплачено картой: 2,000 тг
════════════════════════════════════════
БОНУСНАЯ ПРОГРАММА SAGI:
• Начислены бонусы: 100 тг
• Выдана НАГРАДА за 10 штампов!
• Штампов осталось: 0/10
════════════════════════════════════════
Сценарий 4: Обработка ошибок¶
При неверном коде подтверждения¶
HTTP 400 Bad Request
Действие: Показать сообщение "Неверный код. Попробуйте еще раз" и повторить ввод.При недоступности API¶
╔══════════════════════════════════════╗
║ ВНИМАНИЕ ║
║ ║
║ Сервис бонусов временно недоступен ║
║ Транзакция проведена БЕЗ начисления ║
║ бонусов ║
║ ║
║ Обратитесь в службу поддержки ║
╚══════════════════════════════════════╝
При ошибке настройки подарка¶
╔══════════════════════════════════════╗
║ Товар-подарок не настроен ║
║ ║
║ Обратитесь к администратору ║
║ для настройки программы наград ║
╚══════════════════════════════════════╝
Сценарий 5: Отмена и возвраты¶
Полная отмена транзакции¶
Частичный возврат¶
PATCH /api/v1/orders/{order_id}/refund
{
"amount": 500 # Возврат 500 тенге из 2000
}
# Возвращает пропорциональные бонусы, штампы остаются
Особенности реализации¶
Проверки перед началом работы¶
- Токен валиден: Проверять срок действия токена при запуске смены
- Настройки филиала: Загружать настройки наград (
configuration.award.enabled) - Товар-подарок: Проверять наличие настроенного товара для наград
Логирование для аудита¶
[2024-03-15 14:30:00] USER_SEARCH: phone=+77071234567, found=true, user_id=1460220481801031680
[2024-03-15 14:30:15] BONUS_TRANSACTION: order_id=60f1b2b3c4d5e6f7g8h9i0j1, amount=2000, bonus_used=0, cashback=100
[2024-03-15 14:30:20] STAMP_ADDED: user_id=1460220481801031680, stamps=1, total=8/10
[2024-03-15 14:30:25] TRANSACTION_COMPLETE: order_id=60f1b2b3c4d5e6f7g8h9i0j1, status=completed
Безопасность¶
- Никогда не логировать коды подтверждения
- Хранить токены в безопасном месте
- Очищать поля ввода кода после использования
- Ограничить время ожидания кода подтверждения (5 минут)
Производительность¶
- Кешировать информацию о филиале (group_id, настройки)
- Использовать локальное хранение для токенов
- Реализовать повторные попытки для критичных операций
- Показывать индикаторы загрузки для API запросов
Сценарий 6: Управление токенами авторизации¶
Проактивное обновление токенов¶
Настройка автоматического обновления¶
Скрипт обновления токена¶
#!/bin/bash
CURRENT_TOKEN="your_current_token"
API_BASE="https://gateway.sagi.kz"
# Попытка обновления токена
RESPONSE=$(curl -s -w "%{http_code}" -X POST "$API_BASE/api/v1/auth/refresh_token" \
-H "Authorization: Bearer $CURRENT_TOKEN" \
-o /tmp/refresh_response.json)
HTTP_CODE="${RESPONSE: -3}"
if [ "$HTTP_CODE" -eq 200 ]; then
# Успешное обновление - сохранить новый токен
NEW_TOKEN=$(jq -r '.token' /tmp/refresh_response.json)
echo "$NEW_TOKEN" > /secure/path/token_storage
logger "Token refreshed successfully"
else
# Ошибка обновления - требуется повторная авторизация
logger "Token refresh failed with code $HTTP_CODE - manual re-authentication required"
# Уведомить администратора
fi
Обработка истечения токена в POS¶
Проверка токена перед критическими операциями¶
╔══════════════════════════════════════╗
║ Проверка авторизации... ║
║ ║
║ Токен истек или недействителен ║
║ ║
║ [Обновить токен] [Войти заново] ║
╚══════════════════════════════════════╝
Автоматическое обновление при ошибке 401¶
# При получении HTTP 401 от любого API:
POST /api/v1/auth/refresh_token
# Если успешно → повторить исходный запрос
# Если ошибка → показать форму авторизации
Безопасность токенов¶
Хранение токенов¶
- Зашифрованное хранилище: Не сохранять токены в открытом виде
- Ограниченное время жизни: Срок действия токена — 365 дней, рекомендуется обновлять раз в сутки
- Ротация: Автоматическое обновление предотвращает компрометацию
Мониторинг токенов¶
[2024-03-15 09:00:00] TOKEN_REFRESH: success, expires_at=2024-03-16T09:00:00Z
[2024-03-15 09:30:00] TOKEN_REFRESH: success, expires_at=2024-03-16T09:30:00Z
[2024-03-15 10:00:00] TOKEN_REFRESH: failed, code=401, action=re-auth_required
Сценарий 7: Работа с процентами кешбека¶
Динамический расчет кешбека¶
Получение актуального процента¶
# Перед каждой транзакцией проверять актуальный процент
GET /api/v1/branches/{branch_id}/cashback?user_id={user_id}&type=direct
Отображение информации о кешбеке¶
╔══════════════════════════════════════╗
║ Клиент: Иван Иванов ║
║ Кешбек: 5% (макс. 500 тенге за день) ║
║ ║
║ Условия кешбека: ║
║ • Мин. сумма покупки: 1000 тенге ║
║ • Лимит транзакций: 5 в день ║
║ • Использовано сегодня: 2/5 ║
╚══════════════════════════════════════╝
Обработка ограничений кешбека¶
Превышение дневного лимита¶
╔══════════════════════════════════════╗
║ ВНИМАНИЕ ║
║ ║
║ Клиент превысил дневной лимит ║
║ транзакций с кешбеком ║
║ ║
║ Кешбек по этой покупке: 0% ║
║ Лимит восстановится завтра ║
╚══════════════════════════════════════╝
Клиент в черном списке¶
# Ответ API при клиенте в черном списке
HTTP 400 Bad Request
{
"code": 3010,
"message": "phone number is in blacklist"
}
Градационный кешбек¶
Расчет по сумме покупок¶
- 0-5,000 тенге/месяц: 3% кешбек
- 5,001-15,000 тенге/месяц: 5% кешбек
- 15,001+ тенге/месяц: 7% кешбек
Расчет по количеству транзакций¶
- 1-10 покупок/месяц: базовый процент
- 11-25 покупок/месяц: +1% к базовому
- 26+ покупок/месяц: +2% к базовому
ПРИМЕЧАНИЕ: Приведенные выше суммы и проценты являются примерами. Все параметры градационного кешбека (пороги сумм, проценты, периоды) настраиваются индивидуально для каждого бизнеса в личном кабинете администратора.