passshift
@passshift
php, js, html5, css

Как гарантировать списание денег с баланса?

Здравствуйте!

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

Есть 2 способа:

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

Что касается CRONа, мы тут обсуждали, и сразу вопросы: а что если сервер упадет, а что если крон выполнится несколько раз и т.д., я понимаю, что можно мутить с историей списание (она полюбому нужна), и при списании сверяться, но это не дает гарантии от параллельного списания.

Хочется услышать мнение тех, кто уже проходил это, интересует сама логика и инструменты. Спасибо!
  • Вопрос задан
  • 220 просмотров
Решения вопроса 2
paulfcdd
@paulfcdd
PHP/Sf/WEB developer
Вам нужен Cron для такого чего-то.
что если крон выполнится несколько раз
- это говорит о том, что вы не до конца понимаете, как работает крон, вам нужно почитать доки. Крон - это серверный демон, он выполняется сугубо по определенным датам/времени, вернее он вызываает команду, которая должна исполняться. нет возможности, чтобы крон выполнился 2 раза за день, если сконфигугрирован выполняться 1 раз в день.
а что если сервер упадет
- если у вас упадет сервер, то не важно, что вы будете использовать, крон или не крон, у вас просто все перестанет работать.
Кроме того, можно в таблицу где у вас хранятся данные о списании, добавить дату списания, и сверяться по ней, что даст гарантию того, что если дата списания сегодняшняя, то не списывать и тд. Вообще, такс на самом деле очень простой, заключается в конфигурации крона и написании достаточно простой команды для него с не очень сложной логикой и логгированием каждого списания.
Ответ написан
@402d
начинал с бейсика на УКНЦ в 1988
Они Вам нужны 30(31) * число клиентов записей списаний.

Дано :
Баланс на начало месяца.
Получено в этом месяце.
Услуга 1 АКТИВНА: 300 рублей / месяц
Услуга 2 АКТИВНА : 100 рублей / месяц
Услуга 3 ЗАКОНЧЕНА (5 числа) : 100 рублей / месяц
Услуга 4 ПОДКЛЮЧЕНА ( 20 числа): 300 рублей / месяц

Прошло дней с начала месяца
Дней в месяце

Баланс = Баланс на начало месяца + Получено в этом месяце
- 300 / Дней в месяце * Прошло дней с начала месяца
- 100 / Дней в месяце * Прошло дней с начала месяца
- 100 / Дней в месяце * min ( день завершения, Прошло дней с начала месяца)
- 300 / Дней в месяце * max(0, ( Прошло дней с начала месяца - число подключения ))

в результате нужно будет только раз в месяц обработку базы делать
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
qonand
@qonand
Software Engineer
без разницы как Вы будете запускать процесс списания средств по крону или еще как-то, защита от повторного/параллельного списания должна быть реализована в самом алгоритме списания и не зависеть от вызывающих ее процессов. Т.е. на момент списания алгоритм сам должен проверять нужно ли снимать абонплату с клиента или нет. Как именно сделать эту защиту зависит от деталей реализации Вашей системы - но в общем случае вариант с историей вполне уместен, а проблемы параллельного списания вполне можно решить транзакциями/блокировками
Ответ написан
webinar
@webinar Куратор тега Веб-разработка
Учим yii: https://youtu.be/-WRMlGHLgRg
1. CRON

а что если сервер упадет

Другие решения при упавшем сервере по Вашему будут отлично работать?

а что если крон выполнится несколько раз

с какого перепугу? Тогда предлагаю еще предусмотреть более вероятный вариант, что если нападут инопланетяне? Или деньги завтра отменят - тоже ведь может быть.

что можно мутить с историей списание (она полюбому нужна), и при списании сверяться, но это не дает гарантии от параллельного списания

Почему это не дает гарантии? Если есть запись о списании в этом месяце - не списываем. Как это может не работать? Вижу только вариант с коллапсом вселенной или временной отменой "1+1=2".

интересует сама логика и инструменты

Инструменты: cron + php
Логика: запустились, выбрали из базы кого списывать, списали, записали в БД что списали и сменили статус на оплачено. Опционально, ведем отдельный лог в txt файле, что когда и как.
Ответ написан
Комментировать
Sanasol
@Sanasol Куратор тега Веб-разработка
нельзя просто так взять и загуглить ошибку
а что если

так до бесконечности можно, нужно просто сесть и начать делать.

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

Если сервер упадёт то в любом случае надо либо руками разгребать что произошло и что надо подправить/запустить кроны или еще что-то, либо рассчитывать код на то что вчера допустим крон не отработал, и надо захватить все еще не продленных клиентов и попробовать их продлить. Т.е. по сути тупо как обычно продлить тем кому пришла пора продлять.
Например даже с сегодняшней даты если продлять, то ничего страшного не случится с ними.
Прошедший день станет бесплатным, если вы конечно не хотите брать деньги даже за дни которые ваш сервер лежал.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы