130 lines
4.9 KiB
PHP
130 lines
4.9 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
namespace app\api\logic;
|
||
|
||
use app\api\cache\UserCache;
|
||
use app\dice\model\player\DicePlayer;
|
||
use app\dice\model\player_ticket_record\DicePlayerTicketRecord;
|
||
use app\dice\model\player_wallet_record\DicePlayerWalletRecord;
|
||
use plugin\saiadmin\exception\ApiException;
|
||
use support\think\Db;
|
||
|
||
/**
|
||
* 购买抽奖券套餐:次数 => [消耗coin, 购买次数paid, 赠送次数free]
|
||
* 仅支持 1、5、10 档
|
||
*/
|
||
class GameLogic
|
||
{
|
||
public const PACKAGES = [
|
||
1 => ['coin' => 100, 'paid' => 1, 'free' => 0], // 1次/100coin
|
||
5 => ['coin' => 500, 'paid' => 5, 'free' => 1], // 5张/500coin(5购买+1赠送,共6次)
|
||
10 => ['coin' => 1000, 'paid' => 10, 'free' => 3], // 10张/1000coin(10购买+3赠送,共13次)
|
||
];
|
||
|
||
/** 钱包流水类型:购买抽奖次数 */
|
||
public const WALLET_TYPE_BUY_DRAW = 2;
|
||
|
||
/**
|
||
* 购买抽奖券
|
||
* 先更新 Redis 玩家信息(后续游玩从 Redis 读),再用事务更新数据库;事务失败则回滚 Redis
|
||
* @param int $playerId 玩家ID
|
||
* @param int $count 购买档位:1 / 5 / 10
|
||
* @return array 更新后的 coin, total_ticket_count, paid_ticket_count, free_ticket_count
|
||
*/
|
||
public function buyLotteryTickets(int $playerId, int $count): array
|
||
{
|
||
if (!isset(self::PACKAGES[$count])) {
|
||
throw new ApiException('购买抽奖券错误');
|
||
}
|
||
$pack = self::PACKAGES[$count];
|
||
$cost = $pack['coin'];
|
||
$addPaid = $pack['paid'];
|
||
$addFree = $pack['free'];
|
||
$addTotal = $addPaid + $addFree;
|
||
|
||
$player = DicePlayer::find($playerId);
|
||
if (!$player) {
|
||
throw new ApiException('用户不存在');
|
||
}
|
||
$coinBefore = (float) $player->coin;
|
||
if ($coinBefore < $cost) {
|
||
throw new ApiException('平台币不足');
|
||
}
|
||
|
||
$coinAfter = $coinBefore - $cost;
|
||
$totalBefore = (int) ($player->total_ticket_count ?? 0);
|
||
$paidBefore = (int) ($player->paid_ticket_count ?? 0);
|
||
$freeBefore = (int) ($player->free_ticket_count ?? 0);
|
||
$totalAfter = $totalBefore + $addTotal;
|
||
$paidAfter = $paidBefore + $addPaid;
|
||
$freeAfter = $freeBefore + $addFree;
|
||
|
||
$oldUserArr = $player->hidden(['password'])->toArray();
|
||
$updatedUserArr = $oldUserArr;
|
||
$updatedUserArr['coin'] = $coinAfter;
|
||
$updatedUserArr['total_ticket_count'] = $totalAfter;
|
||
$updatedUserArr['paid_ticket_count'] = $paidAfter;
|
||
$updatedUserArr['free_ticket_count'] = $freeAfter;
|
||
|
||
UserCache::setUser($playerId, $updatedUserArr);
|
||
|
||
$adminId = ($player->admin_id ?? null) ? (int) $player->admin_id : null;
|
||
try {
|
||
Db::transaction(function () use (
|
||
$player,
|
||
$playerId,
|
||
$adminId,
|
||
$cost,
|
||
$coinBefore,
|
||
$coinAfter,
|
||
$addTotal,
|
||
$addPaid,
|
||
$addFree,
|
||
$totalAfter,
|
||
$paidAfter,
|
||
$freeAfter
|
||
) {
|
||
$player->coin = $coinAfter;
|
||
$player->total_ticket_count = $totalAfter;
|
||
$player->paid_ticket_count = $paidAfter;
|
||
$player->free_ticket_count = $freeAfter;
|
||
$player->save();
|
||
|
||
DicePlayerWalletRecord::create([
|
||
'player_id' => $playerId,
|
||
'admin_id' => $adminId,
|
||
'coin' => -$cost,
|
||
'type' => self::WALLET_TYPE_BUY_DRAW,
|
||
'wallet_before' => $coinBefore,
|
||
'wallet_after' => $coinAfter,
|
||
'total_ticket_count' => $addTotal,
|
||
'paid_ticket_count' => $addPaid,
|
||
'free_ticket_count' => $addFree,
|
||
'remark' => "购买抽奖券{$addTotal}次(付费{$addPaid}次+赠送{$addFree}次)",
|
||
]);
|
||
|
||
DicePlayerTicketRecord::create([
|
||
'player_id' => $playerId,
|
||
'admin_id' => $adminId,
|
||
'use_coins' => $cost,
|
||
'total_ticket_count' => $addTotal,
|
||
'paid_ticket_count' => $addPaid,
|
||
'free_ticket_count' => $addFree,
|
||
'remark' => "购买抽奖券{$addTotal}次(付费{$addPaid}次+赠送{$addFree}次)",
|
||
]);
|
||
});
|
||
} catch (\Throwable $e) {
|
||
UserCache::setUser($playerId, $oldUserArr);
|
||
throw $e;
|
||
}
|
||
|
||
return [
|
||
'coin' => (float) $coinAfter,
|
||
'total_ticket_count' => (int) $totalAfter,
|
||
'paid_ticket_count' => (int) $paidAfter,
|
||
'free_ticket_count' => (int) $freeAfter,
|
||
];
|
||
}
|
||
}
|