统一用户信息付费查看
This commit is contained in:
@@ -19,6 +19,9 @@ use App\Models\UserCurrencyLog;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 类功能:统一处理用户经验、金币与魅力变更,并记录对应流水。
|
||||
*/
|
||||
class UserCurrencyService
|
||||
{
|
||||
/**
|
||||
@@ -85,6 +88,58 @@ class UserCurrencyService
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 在余额充足时扣除用户流通金币,并返回扣费后的金币余额。
|
||||
*
|
||||
* @param User $user 被扣费用户
|
||||
* @param int $amount 扣费金币数量
|
||||
* @param CurrencySource $source 扣费来源
|
||||
* @param string $remark 扣费备注
|
||||
* @param int|null $roomId 所在房间 ID(可选)
|
||||
*/
|
||||
public function deductGoldIfEnough(
|
||||
User $user,
|
||||
int $amount,
|
||||
CurrencySource $source,
|
||||
string $remark = '',
|
||||
?int $roomId = null,
|
||||
): ?int {
|
||||
if ($amount <= 0) {
|
||||
return (int) $user->jjb;
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($user, $amount, $source, $remark, $roomId): ?int {
|
||||
// 付费查看属于真实消费,先锁定用户行再判断余额,避免并发点击透支金币。
|
||||
$lockedUser = User::query()
|
||||
->whereKey($user->id)
|
||||
->lockForUpdate()
|
||||
->firstOrFail();
|
||||
|
||||
if ((int) $lockedUser->jjb < $amount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 扣除流通金币后写入统一流水,方便后台统计与用户追溯消费来源。
|
||||
$lockedUser->decrement('jjb', $amount);
|
||||
$balanceAfter = (int) $lockedUser->fresh()->jjb;
|
||||
|
||||
UserCurrencyLog::create([
|
||||
'user_id' => $lockedUser->id,
|
||||
'username' => $lockedUser->username,
|
||||
'currency' => 'gold',
|
||||
'amount' => -$amount,
|
||||
'balance_after' => $balanceAfter,
|
||||
'source' => $source->value,
|
||||
'remark' => $remark,
|
||||
'room_id' => $roomId,
|
||||
]);
|
||||
|
||||
$user->setAttribute('jjb', $balanceAfter);
|
||||
|
||||
return $balanceAfter;
|
||||
}, attempts: 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量变更多个用户的货币属性(适用于自动存点:一次操作多人)。
|
||||
* 每位用户仍独立走事务,单人失败不影响其他人。
|
||||
|
||||
Reference in New Issue
Block a user