youmixx
@youmixx
PHP Developer

Почему не всегда срабатывает код?

Есть сайт на Laravel, к нему подключена платежка.
Есть код, который срабатывает в случае успешного пополнения.

public static function updateDataUser($waitingPayment, $balance)
{

    try {
        DB::beginTransaction();
        $waitingPayment = HistoryPayment::find($waitingPayment->id);
        if ($waitingPayment->status_transaction === 'success') {
            return false;
        }

        $waitingPayment->status_transaction = 'success';
        $waitingPayment->save();

        $user = User::find($waitingPayment->user->id);

        $user->balance += $balance;
        $user->save();

        DB::commit();

    } catch (\Throwable $e) {
        DB::rollBack();
        return false;
    }
    ChangeBalance::dispatch($user->id, $user->balance);
    return true;
}


Как видно, сначала идет присвоение статуса 'success' к операции, а потом уже увеличиваем баланс пользователя.
Проблема в том, что иногда бывает такое, когда статус 'success' присваивается, а баланс просто не прибавляется. Я не понимаю почему это происходит.

Человек пишет в тех.поддержку, мы смотрим на транзакции, видим успешную, а баланса нету и истории покупок тоже. Т.е. реально не засчитали и мы вручную его пополняем. Но естественно это надо исправить.

В чем может быть проблема?
  • Вопрос задан
  • 205 просмотров
Пригласить эксперта
Ответы на вопрос 2
AmdY
@AmdY
PHP и прочие вебштучки
Добавьте логирование, чтобы вы знали что в рамках именно этого $waitingPayment->id поменяли статус и баланс.
п.с. Апдейты надо делать атомарные,
User::where('id', $waitingPayment->user->id)->increment('balance', $balance);
Событие ChangeBalance::dispatch лучше тоже обсервить на уровне модели, а то в другом месте забудете выбросить и сломаете логику.
$waitingPayment->status_transaction - инкапсулируйте всю логику внутри модели, а то вы дважды делаете сравнение со строкой и это потенциально хрупкий код, в случае опечатки даже не заметите.
Ответ написан
Комментировать
LaRN
@LaRN
Senior Developer
Вот тут немного странно сделано:
DB::beginTransaction();
$waitingPayment = HistoryPayment::find($waitingPayment->id);
if ($waitingPayment->status_transaction === 'success') {
return false;
}

Открываем транзакцию, чекаем что status_transaction === 'success' и выходим не закрывая её и не откатывая. Может вынести проверку до открытия транзакции.
Просто открытая тут транзакция может, где-то далее не явно использоваться и возможно влиять на то, что что-то потом откатывается при rollback, что не должно откатывать я.

Есть ещё вызов
ChangeBalance::dispatch($user->id, $user->balance);
Он за пределами основной транзакции и не в try, может он влиять на баланс, например если внутри у него ошибка случается?
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы