Привет, друзья!
Вы же любите no-code/low-code, правда? Кликаете мышкой, перетаскиваете блоки, пьёте капучино — и вуаля, ваше приложение готово! Но стоп. А что, если ваш "волшебный" разработчик на low-code случайно (или специально?) сделал так, что любой школьник может купить у вас iPhone за 10 рублей? Давайте разберёмся, как это возможно, и почему выбор разработчика — это как выбор зубного врача: если ошибётесь, будет больно.
История одной корзины, или почему ваш магазин — не благотворительный фонд
Представьте: у вас есть интернет-магазин. Товары, корзина, заказы — всё как у людей. Всё работает на low-code платформе, чтобы сэкономить бюджет. Но вдруг вы замечаете, что дорогие товары улетают со склада, а деньги не приходят. В чём подвох?
Всё дело в том, как передаются данные о заказе.
❌ Пример "гениального" кода (так делать нельзя!):
Ваш разработчик настроил API так, что клиент сам указывает цену товара. Выглядит это примерно так:
Метод POST /orders
{
"product_id": "123",
"quantity": 1,
"price": 1000 // Ой, а кто это контролирует?
}
Или например, в вашем приложении при тапе на кнопку "Оформить заказ", вы запускаете цикл и записыавете каждую строку заказа в Supabase (no-code/low-code backend на базе PostgreSQL), указывая product_id, quantity, price.
Что происходит:
Злоумышленник перехватывает API и меняет price на 10 рублей, отправляет запрос — и получает товар за копейки. Ваш магазин превращается в филиал "Пятёрочки" с акцией "Всё за 10 рублей".
Как это исправить? Секреты правильных таблиц и API
🔑 Применая структура данных:
Таблица products:
id (уникальный код товара)
name
price (хранится ТОЛЬКО здесь!)
Таблица orders:
id (UUID)
total (сумма заказа)
Таблица order_items:
order_id (ссылка на заказ)
product_id (ссылка на товар)
quantity
price (цена на момент заказа, берётся из products)
✅ Пример умного API:
Клиент отправляет только ID товара и количество. Цену знает только сервер!
{
"items": [
{ "product_id": "8719", "quantity": 2 },
{ "product_id": "8720", "quantity": 3 }
]
}
Пример API в Supabase
Давайте рассмотрим на примере Supabase, который кстати можно установить на свой сервер. Для простоты будем использовать обычные функции в базе данных.
Создадим SQL-функцию bulk_insert_order_items.
Эта функция будет принимать на входе id заказа и список позиций заказа (только id товара и количество. Без указания цен!). А внутри она будет брать из базы цены на товары и считать стоимость по каждой позиции, а также стоимость всего заказа.
CREATE OR REPLACE FUNCTION bulk_insert_order_items(
p_order_id UUID,
p_items JSONB
) RETURNS VOID AS $$
DECLARE
v_total REAL := 0;
v_item RECORD;
BEGIN
-- Перебираем товары и сохраняем их в order_items
FOR v_item IN SELECT * FROM jsonb_to_recordset(p_items) AS (
product_id BIGINT,
quantity REAL
) LOOP
INSERT INTO order_items (order_id, product_id, quantity, price)
SELECT p_order_id, v_item.product_id, v_item.quantity, p.price
FROM products p
WHERE p.id = v_item.product_id
RETURNING price * v_item.quantity INTO v_total;
END LOOP;
-- Обновляем сумму заказа
UPDATE orders
SET total = COALESCE(total, 0) + v_total
WHERE id = p_order_id;
END;
$$ LANGUAGE plpgsql;
2. Проверим работу функции непосредственно через SQL:
select bulk_insert_order_items(
'0f0cbe98-535f-44e4-b842-2c1f06840e9a', -- Замените на валидный UUID заказа
'[{"product_id": 8719, "quantity": 2}, {"product_id": 8720, "quantity": 3}]'::jsonb -- Замените на ваши данные
);
3. Также вы можете использовать Edge Functions, если требуется более сложная логика или интеграция с внешними сервисами. Преимущество Edge Functions в том, что они позволяют контролировать каждый шаг обработки, добавлять кастомные проверки и легко масштабировать решение, что может быть удобнее, если нужна дополнительная гибкость по сравнению с SQL-функциями.
4. Supabase автоматически генерирует API для вызова этой функции. Указываем номер заказа и передаем список товаров и количество, без цен!
curl -X POST 'https://yourproject.supabase.co/rest/v1/rpc/bulk_insert_order_items' \
-d '{
"p_order_id": "0f0cbe98-535f-44e4-b842-2c1f06840e9a",
"p_items": "[{\"product_id\": 8719, \"quantity\": 2}, {\"product_id\": 8720, \"quantity\": 3}]"
}' \
-H "Content-Type: application/json" \
-H "apikey: SUPABASE_KEY" \
-H "Authorization: Bearer SUPABASE_KEY"
Совет заказчикам: Как не нанять "разрушителя бизнесов"
Спросите: «Где считается цена — на сервере или в телефоне клиента?». Если ответ «В интерфейсе», бегите быстрее света.
Проверьте API: Если в запросе есть price, discount или total — это красная лампочка.
Требуйте логов: Все операции с деньгами должны логироваться на сервере.
Узнайте ИТ-бэкграунд вашего специалиста: имеет ли ваш no-code / low-code- разработчик опыт работы разработчиком или системным аналитиком.
Итог: Low-code — это круто, но...
...если ваш разработчик пришел в low-code без базовых принципов разработки ПО, будьте готовы к небезопасным и не оптимизированным приложениям.
P.S. Если после прочтения статьи вы подумали: «А мой API тоже дырявый?» — давайте проверим! Пишите мне в Telegram: @kirilkindn. Устроим вашему приложению «тест-драйв» — бесплатно, с кофе и полезными фидбеками 😉.