Vx

Держи мой актуальный сайт api (бэк) и фронт сайтов. 

Я ставил задачу :

 

Все данные указал.

Открыл в браузере ссылку

{"ok":false,"error":"not_found"}

Тесты :

Оплата сработала.

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

Платежи есть в админке.

Продление сработало.

И проверить в юкассе я делаю вручную. Может сделать периодические проверки автоматически?

Повторно не применилась подписка (не удвоилась) после ручного повтора.

 

Замечания : 

В мини профиле пропала кнопка истории платежей! Косячишь!

 

Кстати я могу накидать Лайт например на год. Потом резко оплатить ultra на месяц и у меня очень много экономии ведь подписка переносится. Нужно математически высчитывать остатки учитывая цену тарифа и скидки в том числе! А то получается абьюз!

Пересчет должен работать в обе стороны и перед оплатой надо этот момент выделить что из-за разницы подписок будет установлен такой-то новый срок. И пересчеты нужны для модулей и тикет workspace.

 

 

после сброса плана (ставлю фри) надо сбрасывать ареда до.хотя когда проект только создался там аренда до - бессрочно. Надо так же сделать.

И владельцу видно интеграции, логи. Тикеты, логи на карте, live map с замочком как надо. Но поидее интеграции и логи надо тоже закрыть замком и писать lite/pro/ultra.

 

Я тут чего придумал. Может проще сделать какой-то кошелек? Который пользователь пополняет на варианты сумм которые мы укажем или на свою сумму от 50 и до лимита юкассы? и потом с него списывает например? Зачем - затем что пользователь может сможет выбрать подписку free и получить остаток средств на кошелек эквивалентно дням подписки? Что думаешь? Но надо как-то продумать это дело, все текстом указать и чтобы не абузили и не использовали как «заморозку»

 

 

 

 

 

Твой ответ был такой, но ты ничего не делаешь т.к. достигнута максимальная длина чата :

{"ok":false,"error":"not_found"} при открытии webhook через браузер — нормально: браузер делает GET, а маршрут ждёт POST.

 

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

 

Автоматическая проверка платежей

 

Да, стоит сделать.

 

Webhook остаётся основным механизмом, а фоновая сверка будет страховкой. ЮKassa прямо допускает два варианта для pending: ждать уведомление или периодически запрашивать состояние платежа.  

 

Предлагаю:

• каждые 5 минут проверять все заказы PENDING, созданные за последние 24 часа;

• затем каждые 30 минут — заказы возрастом до 7 дней;

• после получения succeeded запускать идемпотентное применение;

• после canceled закрывать заказ;

• отдельно раз в сутки сверять последние платежи с ЮKassa;

• сохранять lastCheckedAt, количество попыток и последнюю ошибку.

 

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

 

Пропавшая кнопка истории платежей

 

Это регресс. Кнопку нужно вернуть в мини-профиль и больше не дублировать внутри тарифов:

 

Платежи и покупки

 

Она должна открывать историю для всех проектов пользователя с фильтром по выбранному проекту.

 

Пересчёт подписок

 

Ты прав: текущая схема с переносом даты позволяет купить дешёвый тариф надолго, затем временно перейти на дорогой без правильного списания стоимости.

 

Сроки нельзя просто переносить. Нужно вести денежную стоимость остатка.

 

Правильная модель

 

При смене тарифа считаем кредит текущей подписки:

 

остаточный кредит =

фактически оплаченная сумма × доля неиспользованного срока

 

Именно фактически оплаченная сумма, а не текущая цена из СА. Это важно из-за:

• годовой скидки;

• старых цен;

• промокодов;

• ручных скидок;

• будущего изменения тарифов.

 

Пример:

• Lite на год куплен за 3 600 ₽;

• использовано 60 из 365 дней;

• остаточный кредит ≈ 3 008 ₽;

• Ultra стоит 1 190 ₽ в месяц;

• этот кредит даёт примерно 75–77 дней Ultra, а не остаток старой даты.

 

Точная математика должна идти в секундах или миллисекундах, а итоговая дата округляться по установленному правилу.

 

При переходе вверх и вниз

 

Одинаковая схема в обе стороны:

1. вычислить остаточную стоимость текущего доступа;

2. прибавить новую оплату;

3. определить срок нового продукта по его цене;

4. полностью заменить старое право новым;

5. записать расчёт в заказ, чтобы будущая смена цены его не изменила.

 

Перед оплатой показываем отдельный блок:

 

Остаток текущей подписки: 1 428 ₽

Новая оплата: 1 190 ₽

Общая стоимость доступа после смены: 2 618 ₽

Новый тариф: Ultra

Доступ будет действовать до: 18 ноября 2026

 

И пояснение:

 

При смене тарифа неиспользованная стоимость текущей подписки переносится в новый тариф. Срок меняется в зависимости от стоимости выбранного тарифа.

 

Ticket Workspace и модули

 

Для них нужен тот же принцип, но каждый продукт считается отдельно.

 

Не смешивать всё в один общий остаток:

• основная подписка — собственный баланс стоимости;

• Ticket Workspace — собственный;

• Discord — собственный;

• Telegram — собственный;

• VK — собственный;

• All-in-One — отдельное право либо конвертация входящих каналов.

 

При переходе с отдельных каналов на All-in-One:

 

остаток Discord

+ остаток Telegram

+ остаток VK

+ новая оплата

= срок All-in-One

 

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

 

Сброс на Free

 

При ручном переводе проекта на Free нужно:

 

plan = FREE

subscriptionEndsAt = null

 

В интерфейсе:

 

Аренда до: бессрочно

 

Но здесь важно различать:

• проект существует бессрочно;

• платные возможности не активны.

 

Лучше переименовать поле с Аренда до на:

 

Подписка до

 

А для Free:

 

Подписка: Free, без ограничения срока

 

Замки для интеграций и логов

 

Согласен. Сейчас навигация непоследовательна.

 

Предлагаемая матрица:

 

Раздел Free Lite Pro Ultra

Интеграции 🔒 доступно доступно доступно

Логи 🔒 доступно доступно доступно

Тикеты 🔒 отдельно отдельно доступно

Логи на карте 🔒 🔒 доступно доступно

Live Map 🔒 🔒 🔒 доступно

 

Для Free:

 

Доступно на тарифах Lite, Pro и Ultra

 

Это должно проверяться не только интерфейсом, но и API.

 

Кошелёк

 

Полноценный денежный кошелёк я бы сейчас не делал.

 

Причины:

• появляется хранимый денежный остаток;

• нужно решать возвраты;

• нужно учитывать частичные списания;

• появляется спорная трактовка «денег пользователя на платформе»;

• усложняются чеки, оферта и бухгалтерская логика;

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

 

Более безопасный вариант — внутренний компенсационный баланс, не пополняемый напрямую.

 

Назвать:

 

Баланс компенсации

 

или:

 

Кредит платформы

 

Я бы выбрал «Кредит платформы».

 

Как он работает

 

Кредит появляется только из:

• досрочного отключения платного продукта;

• ручной компенсации СА;

• технической ошибки;

• перехода между несовместимыми продуктами.

 

Его нельзя:

• пополнять отдельно;

• вывести;

• передать другому пользователю;

• использовать в другом проекте;

• получить наличными;

• применять бесконечно без ограничения срока.

 

Защита от заморозки

 

Задать срок действия кредита, например:

 

90 дней

 

И правила:

• кредит привязан к проекту;

• применяется автоматически при следующей покупке;

• сначала списывается кредит, затем ЮKassa;

• не продлевается при новых конвертациях;

• при повторном переходе срок истечения остаётся первоначальным;

• Free не замораживает подписку, а конвертирует остаток в кредит;

• минимальный остаток меньше 1 ₽ списывается;

• все операции фиксируются в истории.

 

Пример:

 

Остаток подписки: 742,18 ₽

После перехода на Free сумма будет зачислена как кредит платформы.

Кредит действует до 21 октября 2026.

Кредит нельзя вывести или передать.

 

Пополнение на произвольную сумму

 

Пока не рекомендую.

 

Пользователю проще сразу оплачивать конкретный товар. ЮKassa уже даёт прозрачную связь:

 

один заказ → одна услуга → один платёж → один чек

 

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

 

деньги → баланс → списание за услугу

 

и требует отдельно продумывать, когда именно оказана услуга и что отражать в чеке. Для самозанятого это особенно стоит предварительно согласовать с ЮKassa или бухгалтером, а не внедрять предположениями.

 

Что делаем следующим патчем

1. Возвращаем историю платежей в мини-профиль.

2. Добавляем автоматическую сверку pending.

3. Исправляем Free и бессрочный срок.

4. Закрываем интеграции и логи для Free.

5. Вводим стоимостный пересчёт основной подписки.

6. Добавляем такой же расчёт для Ticket Workspace и каналов.

7. Перед оплатой показываем полный предварительный расчёт.

8. Добавляем таблицу операций пересчёта.

9. Пока не вводим пополняемый кошелёк.

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